Skip to content

Commit

Permalink
#21
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Beauchamp committed Dec 19, 2015
1 parent fc3fd1f commit 08daf8e
Show file tree
Hide file tree
Showing 39 changed files with 1,079 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System.Linq;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.OData.Routing;
using System.Web.OData.Routing.Conventions;
using SwashbuckleODataSample.ODataControllers;

namespace SwashbuckleODataSample
{
public class CustomNavigationPropertyRoutingConvention : EntitySetRoutingConvention
{
public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
{
var controllerType = controllerContext.Controller.GetType();

if (typeof (CustomersController) == controllerType)
{
}
else if (typeof (OrdersController) == controllerType)
{
if (odataPath.PathTemplate.Equals("~/entityset/key/navigation")) //POST OR GET
{
controllerContext.RouteData.Values["customerID"] = (odataPath.Segments[1] as KeyValuePathSegment).Value;
return controllerContext.Request.Method.ToString();
}
if (odataPath.PathTemplate.Equals("~/entityset/key/navigation/key")) //PATCH OR DELETE
{
controllerContext.RouteData.Values["customerID"] = (odataPath.Segments[1] as KeyValuePathSegment).Value;

controllerContext.RouteData.Values["key"] = (odataPath.Segments[3] as KeyValuePathSegment).Value;
return controllerContext.Request.Method.ToString();
}
}

return base.SelectAction(odataPath, controllerContext, actionMap);
}

public override string SelectController(ODataPath odataPath, HttpRequestMessage request)
{
// We use always use the last naviation as the controller vs. the initial entityset
if (odataPath.PathTemplate.Contains("~/entityset/key/navigation"))
{
// Find controller. Controller should be last navigation property
return ODataSegmentKinds.Navigation == odataPath.Segments[odataPath.Segments.Count - 1].SegmentKind
? odataPath.Segments[odataPath.Segments.Count - 1].ToString()
: odataPath.Segments[odataPath.Segments.Count - 2].ToString();
}
return base.SelectController(odataPath, request);
}
}
}
20 changes: 18 additions & 2 deletions Swashbuckle.OData.Sample/App_Start/ODataConfig.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
using System.Web.Http;
using System.Collections.Generic;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using System.Web.Http.Dispatcher;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Routing;
using System.Web.OData.Routing.Conventions;
using Microsoft.OData.Edm;
using Microsoft.Restier.EntityFramework;
using Microsoft.Restier.WebApi;
using Microsoft.Restier.WebApi.Batch;
using Swashbuckle.OData;
using Swashbuckle.OData.Descriptions;
using SwashbuckleODataSample.Models;
using SwashbuckleODataSample.Repositories;
using SwashbuckleODataSample.Versioning;
Expand Down Expand Up @@ -40,7 +47,16 @@ private static void ConfigureWebApiOData(HttpConfiguration config)
config.MapODataServiceRoute("odata/v2", "odata/v2", GetFakeModel());
controllerSelector.RouteVersionSuffixMapping.Add("odata/v2", "V2");

// Define a default non-versioned route
// Define a custom route with custom routing conventions
var conventions = ODataRoutingConventions.CreateDefault();
conventions.Insert(0, new CustomNavigationPropertyRoutingConvention());
var customODataRoute = config.MapODataServiceRoute("CustomODataRoute", ODataRoutePrefix, GetModel(), batchHandler: null, pathHandler: new DefaultODataPathHandler(), routingConventions: conventions);
config.AddCustomSwaggerRoute(customODataRoute, "/Customers({Id})/Orders")
.Operation(HttpMethod.Post)
.PathParameter<int>("Id")
.BodyParameter<Order>("order");

// Define a default non-versioned route (default route should be at the end as a last catch-all)
config.MapODataServiceRoute("DefaultODataRoute", ODataRoutePrefix, GetModel());
}

Expand Down
21 changes: 21 additions & 0 deletions Swashbuckle.OData.Sample/ODataControllers/OrdersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,27 @@ public IQueryable<Order> GetOrders()
return _db.Orders;
}

/// <summary>
/// Create a new order for the customer with the given <paramref name="customerId"/>
/// </summary>
/// <param name="customerId">The customer id</param>
/// <param name="order">Order details</param>
[ResponseType(typeof(Order))]
public async Task<IHttpActionResult> Post([FromODataUri] int customerId, Order order)
{
order.OrderId = SequentialGuidGenerator.Generate(SequentialGuidType.SequentialAtEnd);

if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}

_db.Orders.Add(order);
await _db.SaveChangesAsync();

return Created(order);
}

/// <summary>
/// Query the order by id
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions Swashbuckle.OData.Sample/Swashbuckle.OData.Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
<Compile Include="ApiControllers\Client.cs" />
<Compile Include="ApiControllers\ClientsController.cs" />
<Compile Include="ApiControllers\Project.cs" />
<Compile Include="App_Start\CustomNavigationPropertyRoutingConvention.cs" />
<Compile Include="App_Start\FormatterConfig.cs" />
<Compile Include="App_Start\SwaggerConfig.cs" />
<Compile Include="App_Start\ODataConfig.cs" />
Expand Down
33 changes: 33 additions & 0 deletions Swashbuckle.OData.Tests/Fixtures/CustomRouteTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Owin.Hosting;
using NUnit.Framework;
using Swashbuckle.OData.Tests.WebHost;
using Swashbuckle.Swagger;
using SwashbuckleODataSample;

namespace Swashbuckle.OData.Tests
{
[TestFixture]
public class CustomRouteTests
{
[Test]
public async Task It_allows_definition_of_custom_routes()
{
using (WebApp.Start(TestWebApiStartup.BaseAddress, appBuilder => new TestWebApiStartup().Configuration(appBuilder)))
{
// Arrange
var httpClient = HttpClientUtils.GetHttpClient(TestWebApiStartup.BaseAddress, ODataConfig.ODataRoutePrefix);

// Act
var swaggerDocument = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1");

// Assert
PathItem pathItem;
swaggerDocument.paths.TryGetValue("/odata/Customers({Id})/Orders", out pathItem);
pathItem.Should().NotBeNull();
pathItem.post.Should().NotBeNull();
}
}
}
}
3 changes: 2 additions & 1 deletion Swashbuckle.OData.Tests/Fixtures/RestierTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ public async Task It_supports_entities_with_multiple_keys()

// Assert
PathItem pathItem;
swaggerDocument.paths.TryGetValue("/restier/Order_Details(OrderID={OrderID}, ProductID={ProductID})", out pathItem);
swaggerDocument.paths.TryGetValue("/restier/OrderDetails(OrderId={OrderId}, ProductId={ProductId})", out pathItem);
pathItem.Should().NotBeNull();
var getResponse = pathItem.get.responses.SingleOrDefault(response => response.Key == "200");
getResponse.Should().NotBeNull();
}
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/NorthwindAPI/Category.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public Category()
Products = new HashSet<Product>();
}

public int CategoryID { get; set; }
public int CategoryId { get; set; }

[Required]
[StringLength(15)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public CustomerDemographic()

[Key]
[StringLength(10)]
public string CustomerTypeID { get; set; }
public string CustomerTypeId { get; set; }

[Column(TypeName = "ntext")]
public string CustomerDesc { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/NorthwindAPI/Employee.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public Employee()
Territories = new HashSet<Territory>();
}

public int EmployeeID { get; set; }
public int EmployeeId { get; set; }

[Required]
[StringLength(20)]
Expand Down
14 changes: 7 additions & 7 deletions Swashbuckle.OData.Tests/NorthwindAPI/NorthwindContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public NorthwindContext() : base("name=NorthwindContext")
public virtual DbSet<CustomerDemographic> CustomerDemographics { get; set; }
public virtual DbSet<NorthwindCustomer> Customers { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<Order_Detail> Order_Details { get; set; }
public virtual DbSet<OrderDetail> OrderDetails { get; set; }
public virtual DbSet<NorthwindOrder> Orders { get; set; }
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<Region> Regions { get; set; }
Expand All @@ -27,27 +27,27 @@ public NorthwindContext() : base("name=NorthwindContext")

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<CustomerDemographic>().Property(e => e.CustomerTypeID).IsFixedLength();
modelBuilder.Entity<CustomerDemographic>().Property(e => e.CustomerTypeId).IsFixedLength();

modelBuilder.Entity<CustomerDemographic>().HasMany(e => e.Customers).WithMany(e => e.CustomerDemographics).Map(m => m.ToTable("CustomerCustomerDemo").MapLeftKey("CustomerTypeID").MapRightKey("CustomerID"));

modelBuilder.Entity<NorthwindCustomer>().Property(e => e.CustomerID).IsFixedLength();
modelBuilder.Entity<NorthwindCustomer>().Property(e => e.CustomerId).IsFixedLength();

modelBuilder.Entity<Employee>().HasMany(e => e.Employees1).WithOptional(e => e.Employee1).HasForeignKey(e => e.ReportsTo);

modelBuilder.Entity<Employee>().HasMany(e => e.Territories).WithMany(e => e.Employees).Map(m => m.ToTable("EmployeeTerritories").MapLeftKey("EmployeeID").MapRightKey("TerritoryID"));

modelBuilder.Entity<Order_Detail>().Property(e => e.UnitPrice).HasPrecision(19, 4);
modelBuilder.Entity<OrderDetail>().Property(e => e.UnitPrice).HasPrecision(19, 4);

modelBuilder.Entity<NorthwindOrder>().Property(e => e.CustomerID).IsFixedLength();
modelBuilder.Entity<NorthwindOrder>().Property(e => e.CustomerId).IsFixedLength();

modelBuilder.Entity<NorthwindOrder>().Property(e => e.Freight).HasPrecision(19, 4);

modelBuilder.Entity<NorthwindOrder>().HasMany(e => e.Order_Details).WithRequired(e => e.NorthwindOrder).WillCascadeOnDelete(false);
modelBuilder.Entity<NorthwindOrder>().HasMany(e => e.OrderDetails).WithRequired(e => e.NorthwindOrder).WillCascadeOnDelete(false);

modelBuilder.Entity<Product>().Property(e => e.UnitPrice).HasPrecision(19, 4);

modelBuilder.Entity<Product>().HasMany(e => e.Order_Details).WithRequired(e => e.Product).WillCascadeOnDelete(false);
modelBuilder.Entity<Product>().HasMany(e => e.OrderDetails).WithRequired(e => e.Product).WillCascadeOnDelete(false);

modelBuilder.Entity<Region>().Property(e => e.RegionDescription).IsFixedLength();

Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/NorthwindAPI/NorthwindCustomer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public NorthwindCustomer()

[Key]
[StringLength(5)]
public string CustomerID { get; set; }
public string CustomerId { get; set; }

[Required]
[StringLength(40)]
Expand Down
10 changes: 5 additions & 5 deletions Swashbuckle.OData.Tests/NorthwindAPI/NorthwindOrder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ public class NorthwindOrder
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public NorthwindOrder()
{
Order_Details = new HashSet<Order_Detail>();
OrderDetails = new HashSet<OrderDetail>();
}

[Key]
public int OrderID { get; set; }
public int OrderId { get; set; }

[StringLength(5)]
public string CustomerID { get; set; }
public string CustomerId { get; set; }

public int? EmployeeID { get; set; }
public int? EmployeeId { get; set; }

public DateTime? OrderDate { get; set; }

Expand Down Expand Up @@ -56,7 +56,7 @@ public NorthwindOrder()
public virtual Employee Employee { get; set; }

[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Order_Detail> Order_Details { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }

public virtual Shipper Shipper { get; set; }
}
Expand Down
6 changes: 3 additions & 3 deletions Swashbuckle.OData.Tests/NorthwindAPI/Order_Detail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
namespace NorthwindAPI.Models
{
[Table("Order Details")]
public class Order_Detail
public class OrderDetail
{
[Key]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int OrderID { get; set; }
public int OrderId { get; set; }

[Key]
[Column(Order = 1)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ProductID { get; set; }
public int ProductId { get; set; }

[Column(TypeName = "money")]
public decimal UnitPrice { get; set; }
Expand Down
10 changes: 5 additions & 5 deletions Swashbuckle.OData.Tests/NorthwindAPI/Product.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ public class Product
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Product()
{
Order_Details = new HashSet<Order_Detail>();
OrderDetails = new HashSet<OrderDetail>();
}

public int ProductID { get; set; }
public int ProductId { get; set; }

[Required]
[StringLength(40)]
public string ProductName { get; set; }

public int? SupplierID { get; set; }
public int? SupplierId { get; set; }

public int? CategoryID { get; set; }
public int? CategoryId { get; set; }

[StringLength(20)]
public string QuantityPerUnit { get; set; }
Expand All @@ -40,7 +40,7 @@ public Product()
public virtual Category Category { get; set; }

[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Order_Detail> Order_Details { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }

public virtual Supplier Supplier { get; set; }
}
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/NorthwindAPI/Region.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public Region()
}

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int RegionID { get; set; }
public int RegionId { get; set; }

[Required]
[StringLength(50)]
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/NorthwindAPI/Shipper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public Shipper()
Orders = new HashSet<NorthwindOrder>();
}

public int ShipperID { get; set; }
public int ShipperId { get; set; }

[Required]
[StringLength(40)]
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData.Tests/NorthwindAPI/Supplier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public Supplier()
Products = new HashSet<Product>();
}

public int SupplierID { get; set; }
public int SupplierId { get; set; }

[Required]
[StringLength(40)]
Expand Down
4 changes: 2 additions & 2 deletions Swashbuckle.OData.Tests/NorthwindAPI/Territory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ public Territory()
}

[StringLength(20)]
public string TerritoryID { get; set; }
public string TerritoryId { get; set; }

[Required]
[StringLength(50)]
public string TerritoryDescription { get; set; }

public int RegionID { get; set; }
public int RegionId { get; set; }

public virtual Region Region { get; set; }

Expand Down
1 change: 1 addition & 0 deletions Swashbuckle.OData.Tests/Swashbuckle.OData.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
<ItemGroup>
<Compile Include="ApplyNewHostName.cs" />
<Compile Include="ContentType.cs" />
<Compile Include="Fixtures\CustomRouteTests.cs" />
<Compile Include="Fixtures\ODataSwaggerProviderTests.cs" />
<Compile Include="Fixtures\PostTests.cs" />
<Compile Include="Fixtures\PatchTests.cs" />
Expand Down
Loading

0 comments on commit 08daf8e

Please sign in to comment.