Skip to content

Commit

Permalink
Fix issue with merging OData and WebApi SwaggerDocuments
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Beauchamp committed Dec 12, 2015
1 parent 896a39c commit aaf7c2b
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 9 deletions.
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 OData v4 support!</Summary>
<Description>Extends Swashbuckle with OData v4 support!</Description>
<ReleaseNotes>Supports both WebApi and OData endpoints. Groups RESTier endpoints by EntitySet name. Fixes documentation bug.</ReleaseNotes>
<ReleaseNotes>Supports both WebApi and OData endpoints. Groups RESTier endpoints by EntitySet name. Bug fixes. </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.5.0</Version>
<Version>2.5.1</Version>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Swashbuckle.OData\Swashbuckle.OData.csproj" />
Expand Down
4 changes: 2 additions & 2 deletions Swashbuckle.OData.Sample/Versioning/ODataHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static ODataPath CreateODataPath(this HttpRequestMessage request, Uri uri
{
if (uri == null)
{
throw new ArgumentNullException("uri");
throw new ArgumentNullException(nameof(uri));
}

var newRequest = new HttpRequestMessage(HttpMethod.Get, uri);
Expand Down Expand Up @@ -59,7 +59,7 @@ public static TKey GetKeyValue<TKey>(this HttpRequestMessage request, Uri uri)
{
if (uri == null)
{
throw new ArgumentNullException("uri");
throw new ArgumentNullException(nameof(uri));
}

//get the odata path Ex: ~/entityset/key/$links/navigation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static void MapODataServiceRoute(
{
if (routes == null)
{
throw new ArgumentNullException("routes");
throw new ArgumentNullException(nameof(routes));
}

string routeTemplate = string.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.ODataPathTemplate : routePrefix + "/" + ODataRouteConstants.ODataPathTemplate;
Expand Down
3 changes: 3 additions & 0 deletions Swashbuckle.OData.Tests/WebHost/TestWebApiStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Owin;
using Swashbuckle.Application;
using SwashbuckleODataSample;
using SwashbuckleODataSample.DocumentFilters;

namespace Swashbuckle.OData.Tests.WebHost
{
Expand Down Expand Up @@ -30,6 +31,8 @@ public void Configuration(IAppBuilder appBuilder, Action<SwaggerDocsConfig> unit
httpConfiguration
.EnableSwagger(c =>
{
c.DocumentFilter<ApplyResourceDocumentation>();
// Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
// hold additional metadata for an API. Version and title are required but you can also provide
// additional fields by chaining methods off SingleApiVersion.
Expand Down
4 changes: 2 additions & 2 deletions Swashbuckle.OData/CollectionExtentions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public static void AddIfNotNull<T>(this Collection<T> source, T item)
}
}

public static IEnumerable<T> UnionEvenIfNull<T>(this IEnumerable<T> source, IEnumerable<T> other)
public static IEnumerable<T> UnionEvenIfNull<T>(this IEnumerable<T> source, IEnumerable<T> other, IEqualityComparer<T> comparer = null)
{
var nonNullSource = source ?? new List<T>();
var nonNullOther = other ?? new List<T>();

return nonNullSource.Union(nonNullOther);
return nonNullSource.Union(nonNullOther, comparer ?? System.Collections.Generic.EqualityComparer<T>.Default);
}
}
}
151 changes: 151 additions & 0 deletions Swashbuckle.OData/EqualityComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;

namespace Swashbuckle.OData
{
/// <summary>
/// Non-generic class to produce instances of the generic class,
/// optionally using type inference.
/// </summary>
public static class EqualityComparer
{
/// <summary>
/// Creates an instance of ProjectionEqualityComparer using the specified projection.
/// </summary>
/// <typeparam name="TSource">Type parameter for the elements to be compared</typeparam>
/// <typeparam name="TKey">
/// Type parameter for the keys to be compared,
/// after being projected from the elements
/// </typeparam>
/// <param name="projection">Projection to use when determining the key of an element</param>
/// <returns>
/// A comparer which will compare elements by projecting
/// each element to its key, and comparing keys
/// </returns>
public static EqualityComparer<TSource, TKey> Create<TSource, TKey>(Func<TSource, TKey> projection)
{
return new EqualityComparer<TSource, TKey>(projection);
}

/// <summary>
/// Creates an instance of ProjectionEqualityComparer using the specified projection.
/// The ignored parameter is solely present to aid type inference.
/// </summary>
/// <typeparam name="TSource">Type parameter for the elements to be compared</typeparam>
/// <typeparam name="TKey">
/// Type parameter for the keys to be compared,
/// after being projected from the elements
/// </typeparam>
/// <param name="ignored">Value is ignored - type may be used by type inference</param>
/// <param name="projection">Projection to use when determining the key of an element</param>
/// <returns>
/// A comparer which will compare elements by projecting
/// each element to its key, and comparing keys
/// </returns>
public static EqualityComparer<TSource, TKey> Create<TSource, TKey>(TSource ignored, Func<TSource, TKey> projection)
{
return new EqualityComparer<TSource, TKey>(projection);
}
}

/// <summary>
/// Class generic in the source only to produce instances of the
/// doubly generic class, optionally using type inference.
/// </summary>
public static class EqualityComparer<TSource>
{
/// <summary>
/// Creates an instance of ProjectionEqualityComparer using the specified projection.
/// </summary>
/// <typeparam name="TKey">
/// Type parameter for the keys to be compared,
/// after being projected from the elements
/// </typeparam>
/// <param name="projection">Projection to use when determining the key of an element</param>
/// <returns>
/// A comparer which will compare elements by projecting each element to its key,
/// and comparing keys
/// </returns>
public static EqualityComparer<TSource, TKey> Create<TKey>(Func<TSource, TKey> projection)
{
return new EqualityComparer<TSource, TKey>(projection);
}
}

/// <summary>
/// Comparer which projects each element of the comparison to a key, and then compares
/// those keys using the specified (or default) _comparer for the key type.
/// </summary>
/// <typeparam name="TSource">
/// Type of elements which this _comparer
/// will be asked to compare
/// </typeparam>
/// <typeparam name="TKey">
/// Type of the key projected
/// from the element
/// </typeparam>
public class EqualityComparer<TSource, TKey> : IEqualityComparer<TSource>
{
private readonly IEqualityComparer<TKey> _comparer;
private readonly Func<TSource, TKey> _projection;

/// <summary>
/// Creates a new instance using the specified _projection, which must not be null.
/// The default _comparer for the projected type is used.
/// </summary>
/// <param name="projection">Projection to use during comparisons</param>
public EqualityComparer(Func<TSource, TKey> projection) : this(projection, null)
{
}

/// <summary>
/// Creates a new instance using the specified _projection, which must not be null.
/// </summary>
/// <param name="projection">Projection to use during comparisons</param>
/// <param name="comparer">
/// The _comparer to use on the keys. May be null, in
/// which case the default _comparer will be used.
/// </param>
public EqualityComparer(Func<TSource, TKey> projection, IEqualityComparer<TKey> comparer)
{
if (projection == null)
{
throw new ArgumentNullException(nameof(projection));
}
_comparer = comparer ?? System.Collections.Generic.EqualityComparer<TKey>.Default;
_projection = projection;
}

/// <summary>
/// Compares the two specified values for equality by applying the _projection
/// to each value and then using the equality _comparer on the resulting keys. Null
/// references are never passed to the _projection.
/// </summary>
public bool Equals(TSource x, TSource y)
{
if (x == null && y == null)
{
return true;
}
if (x == null || y == null)
{
return false;
}
return _comparer.Equals(_projection(x), _projection(y));
}

/// <summary>
/// Produces a hash code for the given value by projecting it and
/// then asking the equality _comparer to find the hash code of
/// the resulting key.
/// </summary>
public int GetHashCode(TSource obj)
{
if (obj == null)
{
throw new ArgumentNullException(nameof(obj));
}
return _comparer.GetHashCode(_projection(obj));
}
}
}
2 changes: 1 addition & 1 deletion Swashbuckle.OData/ODataSwaggerProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ private SwaggerDocument MergeODataAndWebApiSwaggerDocs(string rootUrl, string ap
.ToDictionary(group => group.Key, group => group.First());
webApiSwaggerDoc.vendorExtensions = webApiSwaggerDoc.vendorExtensions.UnionEvenIfNull(odataSwaggerDoc.vendorExtensions).ToLookup(pair => pair.Key, pair => pair.Value)
.ToDictionary(group => group.Key, group => group.First());
webApiSwaggerDoc.tags = webApiSwaggerDoc.tags.UnionEvenIfNull(odataSwaggerDoc.tags).ToList();
webApiSwaggerDoc.tags = webApiSwaggerDoc.tags.UnionEvenIfNull(odataSwaggerDoc.tags, EqualityComparer<Tag>.Create(tag => tag.name)).ToList();
webApiSwaggerDoc.consumes = webApiSwaggerDoc.consumes.UnionEvenIfNull(odataSwaggerDoc.consumes).ToList();
webApiSwaggerDoc.security = webApiSwaggerDoc.security.UnionEvenIfNull(odataSwaggerDoc.security).ToList();
webApiSwaggerDoc.produces = webApiSwaggerDoc.produces.UnionEvenIfNull(odataSwaggerDoc.produces).ToList();
Expand Down
2 changes: 1 addition & 1 deletion Swashbuckle.OData/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("2.5.0")]
[assembly: AssemblyInformationalVersion("2.5.1")]
1 change: 1 addition & 0 deletions Swashbuckle.OData/Swashbuckle.OData.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
<Compile Include="HttpConfigurationExtensions.cs" />
<Compile Include="Descriptions\SwaggerToApiExplorerMapper.cs" />
<Compile Include="Descriptions\ODataApiExplorer.cs" />
<Compile Include="EqualityComparer.cs" />
<Compile Include="SwaggerPathGenerator.cs" />
<Compile Include="ODataSwaggerProvider.cs" />
<Compile Include="ODataSwaggerUtilities.cs" />
Expand Down

0 comments on commit aaf7c2b

Please sign in to comment.