Skip to content

Commit

Permalink
Merge pull request #8 from rbeauchamp/feature/5
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Beauchamp committed Dec 7, 2015
2 parents e5d5e27 + 7163d50 commit fe4c8e5
Show file tree
Hide file tree
Showing 47 changed files with 2,014 additions and 269 deletions.
16 changes: 16 additions & 0 deletions License.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,19 @@ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPO
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

------------------------------------------------------------------------------------------------------------------------------

Certain portions of this code is Copyright (c) 2013, Richard Morris - All rights reserved.

For those portions, the following license applies:

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHA
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ Swashbuckle.OData

Extends Swashbuckle with WebApi OData v4 support!

Implements a custom Swagger Provider that converts an Entity Data Model to a Swagger Document.

### <a href="http://swashbuckleodata.azurewebsites.net/swagger/" target="_blank">Try it out!</a> ###

## Getting Started ##
Expand Down
4 changes: 2 additions & 2 deletions Swashbuckle.OData.Nuget/Swashbuckle.OData.NuGet.nuproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
<Owners>Richard Beauchamp</Owners>
<Summary>Extends Swashbuckle with WebApi OData v4 support!</Summary>
<Description>Extends Swashbuckle with WebApi OData v4 support!</Description>
<ReleaseNotes>Simplified configuration, upgraded to .NET 4.5, fixed metadata path in Swagger UI, uses correct OData route prefix</ReleaseNotes>
<ReleaseNotes>Now supports customization of generated swagger docs via SwaggerConfig, Verifies entity data model against the OData API, Customize output with ApiExplorer-supported attributes</ReleaseNotes>
<ProjectUrl>https://github.com/rbeauchamp/Swashbuckle.OData</ProjectUrl>
<LicenseUrl>https://github.com/rbeauchamp/Swashbuckle.OData/blob/master/License.txt</LicenseUrl>
<Copyright>Copyright 2015</Copyright>
<Tags>Swashbuckle Swagger SwaggerUi OData Documentation Discovery Help WebApi AspNet AspNetWebApi Docs WebHost IIS</Tags>
<Version>2.0.0</Version>
<Version>2.1.0</Version>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Swashbuckle.OData\Swashbuckle.OData.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using System.Collections.Generic;

namespace Swashbuckle.OData.Tests
namespace SwashbuckleODataSample.Models
{
public class Customer
public class Client
{
public int Id { get; set; }

public string Name { get; set; }

public IList<Order> Orders { get; set; }
public IList<Project> Projects { get; set; }
}
}
115 changes: 115 additions & 0 deletions Swashbuckle.OData.Sample/ApiControllers/ClientsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using SwashbuckleODataSample.Models;

namespace SwashbuckleODataSample.ApiControllers
{
public class ClientsController : ApiController
{
private readonly SwashbuckleODataContext db = new SwashbuckleODataContext();

// GET: api/Clients
public IQueryable<Client> GetClients()
{
return db.Clients;
}

// GET: api/Clients/5
[ResponseType(typeof (Client))]
public async Task<IHttpActionResult> GetClient(int id)
{
var client = await db.Clients.FindAsync(id);
if (client == null)
{
return NotFound();
}

return Ok(client);
}

// PUT: api/Clients/5
[ResponseType(typeof (void))]
public async Task<IHttpActionResult> PutClient(int id, Client client)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

if (id != client.Id)
{
return BadRequest();
}

db.Entry(client).State = EntityState.Modified;

try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ClientExists(id))
{
return NotFound();
}
throw;
}

return StatusCode(HttpStatusCode.NoContent);
}

// POST: api/Clients
[ResponseType(typeof (Client))]
public async Task<IHttpActionResult> PostClient(Client client)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

db.Clients.Add(client);
await db.SaveChangesAsync();

return CreatedAtRoute("DefaultApi", new
{
id = client.Id
}, client);
}

// DELETE: api/Clients/5
[ResponseType(typeof (Client))]
public async Task<IHttpActionResult> DeleteClient(int id)
{
var client = await db.Clients.FindAsync(id);
if (client == null)
{
return NotFound();
}

db.Clients.Remove(client);
await db.SaveChangesAsync();

return Ok(client);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}

private bool ClientExists(int id)
{
return db.Clients.Count(e => e.Id == id) > 0;
}
}
}
21 changes: 21 additions & 0 deletions Swashbuckle.OData.Sample/ApiControllers/Project.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Web.OData.Builder;
using Microsoft.OData.Edm;

namespace SwashbuckleODataSample.Models
{
public class Project
{
[Key]
public int ProjectId { get; set; }

public string ProjectName { get; set; }

public int ClientId { get; set; }

[ForeignKey("ClientId")]
[ActionOnDelete(EdmOnDeleteAction.Cascade)]
public Client Client { get; set; }
}
}
115 changes: 115 additions & 0 deletions Swashbuckle.OData.Sample/ApiControllers/ProjectsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using SwashbuckleODataSample.Models;

namespace SwashbuckleODataSample.ApiControllers
{
public class ProjectsController : ApiController
{
private readonly SwashbuckleODataContext db = new SwashbuckleODataContext();

[Route("Projects/v1")]
public IQueryable<Project> GetProjects()
{
return db.Projects;
}

[Route("Projects/v1/{id}")]
[ResponseType(typeof (Project))]
public async Task<IHttpActionResult> GetProject(int id)
{
var project = await db.Projects.FindAsync(id);
if (project == null)
{
return NotFound();
}

return Ok(project);
}

[Route("Projects/v1/{id}")]
[ResponseType(typeof (void))]
public async Task<IHttpActionResult> PutProject(int id, Project project)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

if (id != project.ProjectId)
{
return BadRequest();
}

db.Entry(project).State = EntityState.Modified;

try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProjectExists(id))
{
return NotFound();
}
throw;
}

return StatusCode(HttpStatusCode.NoContent);
}

[Route("Projects/v1")]
[ResponseType(typeof (Project))]
public async Task<IHttpActionResult> PostProject(Project project)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

db.Projects.Add(project);
await db.SaveChangesAsync();

return CreatedAtRoute("DefaultApi", new
{
id = project.ProjectId
}, project);
}

[Route("Projects/v1/{id}")]
[ResponseType(typeof (Project))]
public async Task<IHttpActionResult> DeleteProject(int id)
{
var project = await db.Projects.FindAsync(id);
if (project == null)
{
return NotFound();
}

db.Projects.Remove(project);
await db.SaveChangesAsync();

return Ok(project);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}

private bool ProjectExists(int id)
{
return db.Projects.Count(e => e.ProjectId == id) > 0;
}
}
}
31 changes: 31 additions & 0 deletions Swashbuckle.OData.Sample/App_Start/FormatterConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Web.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

namespace SwashbuckleODataSample
{
/// <summary>
/// </summary>
public static class FormatterConfig
{
/// <summary>
/// Registers the specified configuration.
/// </summary>
/// <param name="config">The configuration.</param>
public static void Register(HttpConfiguration config)
{
var formatters = config.Formatters;

formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
MetadataPropertyHandling = MetadataPropertyHandling.Ignore
};

formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());
}
}
}
1 change: 1 addition & 0 deletions Swashbuckle.OData.Sample/App_Start/SwaggerConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Web.Http;
using System.Web.Http.Description;
using Swashbuckle.Application;
using Swashbuckle.OData;
using SwashbuckleODataSample;
Expand Down
6 changes: 6 additions & 0 deletions Swashbuckle.OData.Sample/App_Start/WebApiConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ public static void Register(HttpConfiguration config)
// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

var builder = new ODataConventionModelBuilder();
builder.EntitySet<Customer>("Customers");
builder.EntitySet<Order>("Orders");
Expand Down
1 change: 1 addition & 0 deletions Swashbuckle.OData.Sample/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class WebApiApplication : HttpApplication
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configure(FormatterConfig.Register);
}
}
}
Loading

0 comments on commit fe4c8e5

Please sign in to comment.