-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Displays query string parameters not described by the EDM model or in…
… the ODataRoute. Fixes #62.
- Loading branch information
Richard Beauchamp
committed
Jan 30, 2016
1 parent
b798e0f
commit 8366dc8
Showing
14 changed files
with
360 additions
and
90 deletions.
There are no files selected for viewing
181 changes: 181 additions & 0 deletions
181
Swashbuckle.OData.Tests/Fixtures/QueryStringParameterTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel.DataAnnotations; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using System.Web.OData; | ||
using System.Web.OData.Builder; | ||
using System.Web.OData.Extensions; | ||
using System.Web.OData.Routing; | ||
using FluentAssertions; | ||
using Microsoft.OData.Edm; | ||
using Microsoft.Owin.Hosting; | ||
using NUnit.Framework; | ||
using Owin; | ||
using Swashbuckle.Swagger; | ||
|
||
namespace Swashbuckle.OData.Tests | ||
{ | ||
[TestFixture] | ||
public class QueryStringParameterTests | ||
{ | ||
[Test] | ||
public async Task It_displays_parameters_not_described_in_the_edm_model() | ||
{ | ||
using (WebApp.Start(HttpClientUtils.BaseAddress, appBuilder => FoobarsSetup.Configuration(appBuilder, typeof(FoobarsSetup.FoobarsController)))) | ||
{ | ||
// Arrange | ||
var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress); | ||
// Verify that the OData route in the test controller is valid | ||
var results = await httpClient.GetJsonAsync<ODataResponse<List<FoobarsSetup.Foobar>>>("odata/Foobars?bar=true"); | ||
results.Should().NotBeNull(); | ||
results.Value.Count.Should().Be(2); | ||
|
||
// Act | ||
var swaggerDocument = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1"); | ||
|
||
// Assert | ||
PathItem pathItem; | ||
swaggerDocument.paths.TryGetValue("/odata/Foobars", out pathItem); | ||
pathItem.Should().NotBeNull(); | ||
var barParameter = pathItem.get.parameters.SingleOrDefault(parameter => parameter.name == "bar"); | ||
barParameter.Should().NotBeNull(); | ||
barParameter.required.Should().BeFalse(); | ||
barParameter.type.ShouldBeEquivalentTo("boolean"); | ||
barParameter.@in.ShouldBeEquivalentTo("query"); | ||
var filterParameter = pathItem.get.parameters.SingleOrDefault(parameter => parameter.name == "$filter"); | ||
filterParameter.Should().NotBeNull(); | ||
filterParameter.description.Should().NotBeNullOrWhiteSpace(); | ||
filterParameter.type.ShouldBeEquivalentTo("string"); | ||
filterParameter.@in.ShouldBeEquivalentTo("query"); | ||
|
||
await ValidationUtils.ValidateSwaggerJson(); | ||
} | ||
} | ||
|
||
[Test] | ||
public async Task It_displays_parameters_not_defined_in_the_odata_route() | ||
{ | ||
using (WebApp.Start(HttpClientUtils.BaseAddress, appBuilder => WombatsSetup.Configuration(appBuilder, typeof(WombatsSetup.WombatsController)))) | ||
{ | ||
// Arrange | ||
var httpClient = HttpClientUtils.GetHttpClient(HttpClientUtils.BaseAddress); | ||
// Verify that the OData route in the test controller is valid | ||
var results = await httpClient.GetJsonAsync<ODataResponse<List<WombatsSetup.Wombat>>>("odata/Wombats?bat=true"); | ||
results.Should().NotBeNull(); | ||
results.Value.Count.Should().Be(2); | ||
|
||
// Act | ||
var swaggerDocument = await httpClient.GetJsonAsync<SwaggerDocument>("swagger/docs/v1"); | ||
|
||
// Assert | ||
PathItem pathItem; | ||
swaggerDocument.paths.TryGetValue("/odata/Wombats", out pathItem); | ||
pathItem.Should().NotBeNull(); | ||
var barParameter = pathItem.get.parameters.SingleOrDefault(parameter => parameter.name == "bat"); | ||
barParameter.Should().NotBeNull(); | ||
barParameter.required.Should().BeFalse(); | ||
barParameter.type.ShouldBeEquivalentTo("boolean"); | ||
barParameter.@in.ShouldBeEquivalentTo("query"); | ||
var filterParameter = pathItem.get.parameters.SingleOrDefault(parameter => parameter.name == "$filter"); | ||
filterParameter.Should().NotBeNull(); | ||
filterParameter.description.Should().NotBeNullOrWhiteSpace(); | ||
filterParameter.type.ShouldBeEquivalentTo("string"); | ||
filterParameter.@in.ShouldBeEquivalentTo("query"); | ||
|
||
await ValidationUtils.ValidateSwaggerJson(); | ||
} | ||
} | ||
} | ||
|
||
public class FoobarsSetup | ||
{ | ||
public static void Configuration(IAppBuilder appBuilder, Type targetController) | ||
{ | ||
var config = appBuilder.GetStandardHttpConfig(targetController); | ||
|
||
config.MapODataServiceRoute("odata", "odata", GetEdmModel()); | ||
|
||
config.EnsureInitialized(); | ||
} | ||
|
||
public static IEdmModel GetEdmModel() | ||
{ | ||
var builder = new ODataConventionModelBuilder(); | ||
|
||
builder.EntitySet<Foobar>("Foobars"); | ||
|
||
return builder.GetEdmModel(); | ||
} | ||
|
||
public class Foobar | ||
{ | ||
[Key] | ||
public long Id { get; set; } | ||
public string Variation { get; set; } | ||
} | ||
|
||
public class FoobarsController : ODataController | ||
{ | ||
[EnableQuery] | ||
public IQueryable<Foobar> GetFoobars([FromODataUri] bool? bar = null) | ||
{ | ||
IEnumerable<Foobar> foobars = new[] | ||
{ | ||
new Foobar { Id=1, Variation = "a"}, | ||
new Foobar { Id=2, Variation = "b"}, | ||
new Foobar { Id=3, Variation = "c"}, | ||
new Foobar { Id=4, Variation = "d"} | ||
}; | ||
if (bar != null && bar.Value) foobars = foobars.Where(fb => fb.Id >= 3); | ||
return foobars.AsQueryable(); | ||
} | ||
} | ||
} | ||
|
||
public class WombatsSetup | ||
{ | ||
public static void Configuration(IAppBuilder appBuilder, Type targetController) | ||
{ | ||
var config = appBuilder.GetStandardHttpConfig(targetController); | ||
|
||
config.MapODataServiceRoute("odata", "odata", GetEdmModel()); | ||
|
||
config.EnsureInitialized(); | ||
} | ||
|
||
public static IEdmModel GetEdmModel() | ||
{ | ||
var builder = new ODataConventionModelBuilder(); | ||
|
||
builder.EntitySet<Wombat>("Wombats"); | ||
|
||
return builder.GetEdmModel(); | ||
} | ||
|
||
public class Wombat | ||
{ | ||
[Key] | ||
public long Id { get; set; } | ||
public string Variation { get; set; } | ||
} | ||
|
||
public class WombatsController : ODataController | ||
{ | ||
[EnableQuery] | ||
[ODataRoute("Wombats")] | ||
public IQueryable<Wombat> GetWombats([FromODataUri] bool? bat = null) | ||
{ | ||
IEnumerable<Wombat> wombats = new[] | ||
{ | ||
new Wombat { Id=1, Variation = "a"}, | ||
new Wombat { Id=2, Variation = "b"}, | ||
new Wombat { Id=3, Variation = "c"}, | ||
new Wombat { Id=4, Variation = "d"} | ||
}; | ||
if (bat != null && bat.Value) wombats = wombats.Where(wb => wb.Id >= 3); | ||
return wombats.AsQueryable(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
Swashbuckle.OData/Descriptions/ApiParameterDescriptionEqualityComparer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Web.Http.Controllers; | ||
using System.Web.Http.Description; | ||
|
||
namespace Swashbuckle.OData.Descriptions | ||
{ | ||
internal class ApiParameterDescriptionEqualityComparer : IEqualityComparer<ApiParameterDescription> | ||
{ | ||
public bool Equals(ApiParameterDescription x, ApiParameterDescription y) | ||
{ | ||
return ReferenceEquals(x, y) | ||
|| RootParameterDescriptorsAreEqual(x, y) | ||
|| string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase); | ||
} | ||
|
||
private static bool RootParameterDescriptorsAreEqual(ApiParameterDescription x, ApiParameterDescription y) | ||
{ | ||
var xParameterDescriptor = GetRootParameterDescriptor(x); | ||
var yParameterDescriptor = GetRootParameterDescriptor(y); | ||
|
||
return xParameterDescriptor != null && yParameterDescriptor != null && ReferenceEquals(xParameterDescriptor, yParameterDescriptor); | ||
} | ||
|
||
private static HttpParameterDescriptor GetRootParameterDescriptor(ApiParameterDescription apiParameterDescription) | ||
{ | ||
var oDataParameterDescriptor = apiParameterDescription.ParameterDescriptor as ODataParameterDescriptor; | ||
|
||
return oDataParameterDescriptor != null | ||
? oDataParameterDescriptor.ReflectedHttpParameterDescriptor | ||
: apiParameterDescription.ParameterDescriptor; | ||
} | ||
|
||
public int GetHashCode(ApiParameterDescription obj) | ||
{ | ||
// Make all HashCodes the same to force | ||
// an Equals(ApiParameterDescription x, ApiParameterDescription y) check | ||
return 1; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
Swashbuckle.OData/Descriptions/ODataActionDescriptorEqualityComparer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.Contracts; | ||
|
||
namespace Swashbuckle.OData.Descriptions | ||
{ | ||
internal class ODataActionDescriptorEqualityComparer : IEqualityComparer<ODataActionDescriptor> | ||
{ | ||
public bool Equals(ODataActionDescriptor x, ODataActionDescriptor y) | ||
{ | ||
if (ReferenceEquals(x, y)) | ||
{ | ||
return true; | ||
} | ||
return x.Request.Method.Equals(y.Request.Method) | ||
&& string.Equals(NormalizeRelativePath(x.RelativePathTemplate), NormalizeRelativePath(y.RelativePathTemplate), StringComparison.OrdinalIgnoreCase) | ||
&& x.ActionDescriptor.Equals(y.ActionDescriptor); | ||
} | ||
|
||
public int GetHashCode(ODataActionDescriptor obj) | ||
{ | ||
var hashCode = obj.Request.Method.GetHashCode(); | ||
hashCode = (hashCode * 397) ^ StringComparer.OrdinalIgnoreCase.GetHashCode(NormalizeRelativePath(obj.RelativePathTemplate)); | ||
hashCode = (hashCode * 397) ^ obj.ActionDescriptor.GetHashCode(); | ||
return hashCode; | ||
} | ||
|
||
private static string NormalizeRelativePath(string path) | ||
{ | ||
Contract.Requires(path != null); | ||
|
||
return path.Replace("()", string.Empty); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.