Skip to content

Commit d38d08c

Browse files
Chris Martinezcommonsensesoftware
authored andcommitted
Refactor group name generation into options using ApiVersion formatting
1 parent b846091 commit d38d08c

File tree

27 files changed

+283
-230
lines changed

27 files changed

+283
-230
lines changed

ApiVersioning.sln

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26403.3
4+
VisualStudioVersion = 15.0.26403.7
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D5F5F21-0CB7-4B4E-A42F-732BD4AFD0FF}"
77
EndProject
@@ -58,8 +58,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.OData.Vers
5858
EndProject
5959
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests", "test\Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests\Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests.csproj", "{280C3B03-5EED-40E9-A826-83C9F3C6EEDC}"
6060
EndProject
61+
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Common.ApiExplorer", "src\Common.ApiExplorer\Common.ApiExplorer.shproj", "{26A67334-F6E6-49B8-8C5A-F88F28770966}"
62+
EndProject
6163
Global
6264
GlobalSection(SharedMSBuildProjectFiles) = preSolution
65+
src\Common.ApiExplorer\Common.ApiExplorer.projitems*{26a67334-f6e6-49b8-8c5a-f88f28770966}*SharedItemsImports = 13
6366
test\Acceptance.Test.Shared\Acceptance.Test.Shared.projitems*{6cdfb878-2642-4f98-ae35-621bac581181}*SharedItemsImports = 13
6467
src\Common\Common.projitems*{6d0e834b-6422-44cd-9a85-e3be9dead1be}*SharedItemsImports = 13
6568
src\Shared\Shared.projitems*{b7897873-6757-4684-83c0-39575821ae14}*SharedItemsImports = 13
@@ -149,5 +152,6 @@ Global
149152
{C8D29CB1-C541-4579-A1B8-AFD4B4F5F4A3} = {0987757E-4D09-4523-B9C9-65B1E8832AA1}
150153
{6ED07FE1-95D3-41E9-A0F1-AEF1BBD6A474} = {4D5F5F21-0CB7-4B4E-A42F-732BD4AFD0FF}
151154
{280C3B03-5EED-40E9-A826-83C9F3C6EEDC} = {0987757E-4D09-4523-B9C9-65B1E8832AA1}
155+
{26A67334-F6E6-49B8-8C5A-F88F28770966} = {4D5F5F21-0CB7-4B4E-A42F-732BD4AFD0FF}
152156
EndGlobalSection
153157
EndGlobal

ApiVersioningWithSamples.sln

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26403.3
4+
VisualStudioVersion = 15.0.26403.7
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{4D5F5F21-0CB7-4B4E-A42F-732BD4AFD0FF}"
77
EndProject
@@ -94,8 +94,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.OData.Vers
9494
EndProject
9595
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests", "test\Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests\Microsoft.AspNet.OData.Versioning.ApiExplorer.Tests.csproj", "{3B7E0FEF-8019-4A17-A55F-A6FA378DA856}"
9696
EndProject
97+
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Common.ApiExplorer", "src\Common.ApiExplorer\Common.ApiExplorer.shproj", "{26A67334-F6E6-49B8-8C5A-F88F28770966}"
98+
EndProject
9799
Global
98100
GlobalSection(SharedMSBuildProjectFiles) = preSolution
101+
src\Common.ApiExplorer\Common.ApiExplorer.projitems*{26a67334-f6e6-49b8-8c5a-f88f28770966}*SharedItemsImports = 13
99102
test\Acceptance.Test.Shared\Acceptance.Test.Shared.projitems*{6cdfb878-2642-4f98-ae35-621bac581181}*SharedItemsImports = 13
100103
src\Common\Common.projitems*{6d0e834b-6422-44cd-9a85-e3be9dead1be}*SharedItemsImports = 13
101104
src\Shared\Shared.projitems*{b7897873-6757-4684-83c0-39575821ae14}*SharedItemsImports = 13
@@ -247,5 +250,6 @@ Global
247250
{F3986F7B-AF76-43D1-A44F-303023A08CD3} = {F446ED94-368F-4F67-913B-16E82CA80DFC}
248251
{1B255310-A2B7-437F-804F-6E1D8C940A17} = {4D5F5F21-0CB7-4B4E-A42F-732BD4AFD0FF}
249252
{3B7E0FEF-8019-4A17-A55F-A6FA378DA856} = {0987757E-4D09-4523-B9C9-65B1E8832AA1}
253+
{26A67334-F6E6-49B8-8C5A-F88F28770966} = {4D5F5F21-0CB7-4B4E-A42F-732BD4AFD0FF}
250254
EndGlobalSection
251255
EndGlobal

samples/aspnetcore/SwaggerSample/Startup.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ public Startup( IHostingEnvironment env )
4343
/// <param name="services">The collection of services to configure the application with.</param>
4444
public void ConfigureServices( IServiceCollection services )
4545
{
46-
// add the versioned api explorer, which also adds the following services:
47-
//
48-
// * IApiVersionDescriptionProvider
49-
// * IApiVersionGroupNameFormatter
50-
services.AddMvcCore().AddVersionedApiExplorer();
46+
// add the versioned api explorer, which also adds IApiVersionDescriptionProvider service
47+
// note: the specified format code will format the version as "'v'major[.minor][-status]"
48+
services.AddMvcCore().AddVersionedApiExplorer( o => o.GroupNameFormat = "'v'VVV" );
5149

5250
services.AddMvc();
5351
services.AddApiVersioning( o => o.ReportApiVersions = true );
@@ -79,7 +77,8 @@ public void ConfigureServices( IServiceCollection services )
7977
/// <param name="app">The current application builder.</param>
8078
/// <param name="env">The current hosting environment.</param>
8179
/// <param name="loggerFactory">The logging factory used for instrumentation.</param>
82-
public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory )
80+
/// <param name="provider">The API version descriptor provider used to enumerate defined API versions.</param>
81+
public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider provider )
8382
{
8483
loggerFactory.AddConsole( Configuration.GetSection( "Logging" ) );
8584
loggerFactory.AddDebug();
@@ -89,9 +88,6 @@ public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILogger
8988
app.UseSwaggerUI(
9089
options =>
9190
{
92-
// resolve the IApiVersionDescriptionProvider service
93-
var provider = app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();
94-
9591
// build a swagger endpoint for each discovered API version
9692
foreach ( var description in provider.ApiVersionDescriptions )
9793
{

samples/webapi/SwaggerODataWebApiSample/Startup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ public void Configuration( IAppBuilder builder )
4747
configuration.MapVersionedODataRoutes( "odata-bypath", "api/v{apiVersion}", models, ConfigureODataServices );
4848

4949
// add the versioned IApiExplorer and capture the strongly-typed implementation (e.g. ODataApiExplorer vs IApiExplorer)
50-
var apiExplorer = configuration.AddODataApiExplorer();
50+
// note: the specified format code will format the version as "'v'major[.minor][-status]"
51+
var apiExplorer = configuration.AddODataApiExplorer( o => o.GroupNameFormat = "'v'VVV" );
5152

5253
configuration.EnableSwagger(
5354
"{apiVersion}/swagger",

samples/webapi/SwaggerWebApiSample/Startup.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public void Configuration( IAppBuilder builder )
3232
configuration.MapHttpAttributeRoutes( constraintResolver );
3333

3434
// add the versioned IApiExplorer and capture the strongly-typed implementation (e.g. VersionedApiExplorer vs IApiExplorer)
35-
var apiExplorer = configuration.AddVersionedApiExplorer();
35+
// note: the specified format code will format the version as "'v'major[.minor][-status]"
36+
var apiExplorer = configuration.AddVersionedApiExplorer( o => o.GroupNameFormat = "'v'VVV" );
3637

3738
configuration.EnableSwagger(
3839
"{apiVersion}/swagger",
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#if WEBAPI
2+
namespace Microsoft.Web.Http.Description
3+
#else
4+
namespace Microsoft.AspNetCore.Mvc.ApiExplorer
5+
#endif
6+
{
7+
using System;
8+
using Versioning;
9+
10+
/// <summary>
11+
/// Represents the possible API versioning options for the API explorer.
12+
/// </summary>
13+
public partial class ApiExplorerOptions
14+
{
15+
/// <summary>
16+
/// Gets or sets the format used to create group names from API versions.
17+
/// </summary>
18+
/// <value>The string format used to format an <see cref="ApiVersion">API version</see>
19+
/// as a group name. The default value is <c>null</c>.</value>
20+
/// <remarks>For information about API version formatting, review <see cref="ApiVersionFormatProvider"/>
21+
/// as well as the <see cref="ApiVersion.ToString(string)"/> and <see cref="ApiVersion.ToString(string, IFormatProvider)"/>
22+
/// methods.</remarks>
23+
public string GroupNameFormat { get; set; }
24+
}
25+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
5+
<HasSharedItems>true</HasSharedItems>
6+
<SharedGUID>26a67334-f6e6-49b8-8c5a-f88f28770966</SharedGUID>
7+
</PropertyGroup>
8+
<PropertyGroup Label="Configuration">
9+
<Import_RootNamespace>Microsoft</Import_RootNamespace>
10+
</PropertyGroup>
11+
<ItemGroup>
12+
<Compile Include="$(MSBuildThisFileDirectory)ApiExplorerOptions.cs" />
13+
</ItemGroup>
14+
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup Label="Globals">
4+
<ProjectGuid>26a67334-f6e6-49b8-8c5a-f88f28770966</ProjectGuid>
5+
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
6+
</PropertyGroup>
7+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
8+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
9+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
10+
<PropertyGroup />
11+
<Import Project="Common.ApiExplorer.projitems" Label="Shared" />
12+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
13+
</Project>

src/Microsoft.AspNet.OData.Versioning.ApiExplorer/Description/ODataApiExplorer.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace Microsoft.Web.Http.Description
22
{
3-
using Microsoft.Extensions.DependencyInjection;
43
using Microsoft.OData.Edm;
54
using Microsoft.Web.Http.Routing;
65
using System;
@@ -34,18 +33,23 @@ public class ODataApiExplorer : VersionedApiExplorer
3433
/// Initializes a new instance of the <see cref="ODataApiExplorer"/> class.
3534
/// </summary>
3635
/// <param name="configuration">The current <see cref="HttpConfiguration">HTTP configuration</see>.</param>
37-
public ODataApiExplorer( HttpConfiguration configuration ) : base( configuration ) { }
36+
public ODataApiExplorer( HttpConfiguration configuration ) : this( configuration, new ODataApiExplorerOptions( configuration ) ) { }
3837

3938
/// <summary>
40-
/// Gets or sets a value indicating whether the API explorer settings are honored.
39+
/// Initializes a new instance of the <see cref="ODataApiExplorer"/> class.
40+
/// </summary>
41+
/// <param name="configuration">The current <see cref="HttpConfiguration">HTTP configuration</see>.</param>
42+
/// <param name="options">The associated <see cref="ODataApiExplorerOptions">API explorer options</see>.</param>
43+
public ODataApiExplorer( HttpConfiguration configuration, ODataApiExplorerOptions options ) : base( configuration, options )
44+
{
45+
Options = options;
46+
}
47+
48+
/// <summary>
49+
/// Gets the options associated with the API explorer.
4150
/// </summary>
42-
/// <value>True if the <see cref="ApiExplorerSettingsAttribute"/> is ignored; otherwise, false.
43-
/// The default value is <c>false</c>.</value>
44-
/// <remarks>Most OData services inherit from the <see cref="ODataController"/>, which excludes the controller
45-
/// from the <see cref="IApiExplorer">API explorer</see> by setting <see cref="ApiExplorerSettingsAttribute.IgnoreApi"/>
46-
/// to <c>true</c>. By setting this property to <c>false</c>, these settings are ignored instead of reapplying
47-
/// <see cref="ApiExplorerSettingsAttribute.IgnoreApi"/> with a value of <c>false</c> to all OData controllers.</remarks>
48-
public bool UseApiExplorerSettings { get; set; }
51+
/// <value>The <see cref="ODataApiExplorerOptions">API explorer options</see>.</value>
52+
new protected virtual ODataApiExplorerOptions Options { get; }
4953

5054
/// <summary>
5155
/// Determines whether the action should be considered.
@@ -66,7 +70,7 @@ protected override bool ShouldExploreAction( string actionRouteParameterValue, H
6670
return base.ShouldExploreAction( actionRouteParameterValue, actionDescriptor, route, apiVersion );
6771
}
6872

69-
if ( UseApiExplorerSettings )
73+
if ( Options.UseApiExplorerSettings )
7074
{
7175
var setting = actionDescriptor.GetCustomAttributes<ApiExplorerSettingsAttribute>().FirstOrDefault();
7276

@@ -112,7 +116,7 @@ protected override bool ShouldExploreController( string controllerRouteParameter
112116
return base.ShouldExploreController( controllerRouteParameterValue, controllerDescriptor, route, apiVersion );
113117
}
114118

115-
if ( UseApiExplorerSettings )
119+
if ( Options.UseApiExplorerSettings )
116120
{
117121
var setting = controllerDescriptor.GetCustomAttributes<ApiExplorerSettingsAttribute>().FirstOrDefault();
118122

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace Microsoft.Web.Http.Description
2+
{
3+
using System;
4+
using System.Web.Http;
5+
using System.Web.Http.Description;
6+
using System.Web.OData;
7+
8+
/// <summary>
9+
/// Represents the possible API versioning options for an OData API explorer.
10+
/// </summary>
11+
public class ODataApiExplorerOptions : ApiExplorerOptions
12+
{
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="ODataApiExplorerOptions"/> class.
15+
/// </summary>
16+
/// <param name="configuration">The current <see cref="HttpConfiguration">configuration</see> associated with the options.</param>
17+
public ODataApiExplorerOptions( HttpConfiguration configuration ) : base( configuration ) { }
18+
19+
/// <summary>
20+
/// Gets or sets a value indicating whether the API explorer settings are honored.
21+
/// </summary>
22+
/// <value>True if the <see cref="ApiExplorerSettingsAttribute"/> is ignored; otherwise, false.
23+
/// The default value is <c>false</c>.</value>
24+
/// <remarks>Most OData services inherit from the <see cref="ODataController"/>, which excludes the controller
25+
/// from the <see cref="IApiExplorer">API explorer</see> by setting <see cref="ApiExplorerSettingsAttribute.IgnoreApi"/>
26+
/// to <c>true</c>. By setting this property to <c>false</c>, these settings are ignored instead of reapplying
27+
/// <see cref="ApiExplorerSettingsAttribute.IgnoreApi"/> with a value of <c>false</c> to all OData controllers.</remarks>
28+
public bool UseApiExplorerSettings { get; set; }
29+
}
30+
}

0 commit comments

Comments
 (0)