Skip to content

Commit d39a9a2

Browse files
Fix Action Selector Re-entry in ASP.NET Core (#126)
Refactors the ApiVersionActionSelector and fixes re-entry related issues. Related to #106, #122, and possibly #123.
1 parent ad6dff9 commit d39a9a2

File tree

25 files changed

+588
-133
lines changed

25 files changed

+588
-133
lines changed

samples/aspnetcore/BasicSample/Startup.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
using System.Linq;
1111
using System.Threading.Tasks;
1212

13+
using Microsoft.AspNetCore.Mvc.Routing;
14+
1315
public class Startup
1416
{
1517
public Startup( IHostingEnvironment env )
@@ -27,7 +29,7 @@ public Startup( IHostingEnvironment env )
2729
public void ConfigureServices( IServiceCollection services )
2830
{
2931
services.AddMvc();
30-
32+
3133
// reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
3234
services.AddApiVersioning( o => o.ReportApiVersions = true );
3335
}
@@ -37,6 +39,7 @@ public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILogger
3739
loggerFactory.AddConsole( Configuration.GetSection( "Logging" ) );
3840
loggerFactory.AddDebug();
3941
app.UseMvc();
42+
app.UseApiVersioning();
4043
}
4144
}
4245
}

samples/aspnetcore/ByNamespaceSample/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILogger
2828
}
2929

3030
app.UseMvc();
31+
app.UseApiVersioning();
3132
}
3233
}
3334
}

samples/aspnetcore/ConventionsSample/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILogger
5454
loggerFactory.AddConsole( Configuration.GetSection( "Logging" ) );
5555
loggerFactory.AddDebug();
5656
app.UseMvc();
57+
app.UseApiVersioning();
5758
}
5859
}
5960
}

samples/aspnetcore/SwaggerSample/Startup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILogger
8484
loggerFactory.AddDebug();
8585

8686
app.UseMvc();
87+
app.UseApiVersioning();
8788
app.UseSwagger();
8889
app.UseSwaggerUI(
8990
options =>

src/Microsoft.AspNetCore.Mvc.Versioning/Abstractions/ActionDescriptorExtensions.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using ApplicationModels;
44
using System;
5+
using System.Collections.Generic;
56
using System.Diagnostics.Contracts;
67
using System.Linq;
78
using Versioning;
@@ -18,6 +19,24 @@ public static class ActionDescriptorExtensions
1819

1920
static void HasAggregatedVersions( this ActionDescriptor action, bool value ) => action.Properties[VersionsAggregated] = value;
2021

22+
internal static void AggregateAllVersions( this ActionDescriptor action, IEnumerable<ActionDescriptor> matchingActions )
23+
{
24+
Contract.Requires( action != null );
25+
Contract.Requires( matchingActions != null );
26+
27+
if ( action.HasAggregatedVersions() )
28+
{
29+
return;
30+
}
31+
32+
action.HasAggregatedVersions( true );
33+
34+
var model = action.GetProperty<ApiVersionModel>();
35+
Contract.Assume( model != null );
36+
37+
action.SetProperty( model.Aggregate( matchingActions.Select( a => a.GetProperty<ApiVersionModel>() ).Where( m => m != null ) ) );
38+
}
39+
2140
internal static void AggregateAllVersions( this ActionDescriptor action, ActionSelectionContext context )
2241
{
2342
Contract.Requires( action != null );

src/Microsoft.AspNetCore.Mvc.Versioning/HttpContextExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace Microsoft.AspNetCore.Mvc
22
{
33
using Http;
4+
using Microsoft.AspNetCore.Mvc.Routing;
45
using System;
56
using System.Diagnostics.Contracts;
67
using Versioning;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace Microsoft.Extensions.DependencyInjection
2+
{
3+
using Microsoft.AspNetCore.Builder;
4+
using Microsoft.AspNetCore.Mvc.Routing;
5+
using System;
6+
using System.Diagnostics.Contracts;
7+
8+
/// <summary>
9+
/// Provides extension methods for the <see cref="IApplicationBuilder"/> interface.
10+
/// </summary>
11+
[CLSCompliant( false )]
12+
public static class IApplicationBuilderExtensions
13+
{
14+
/// <summary>
15+
/// Adds API versioning to the <see cref="IApplicationBuilder"/> request execution pipeline.
16+
/// </summary>
17+
/// <param name="app">The <see cref="IApplicationBuilder">application builder</see> to add API versioning to.</param>
18+
/// <returns>The original <see cref="IApplicationBuilder"/>.</returns>
19+
public static IApplicationBuilder UseApiVersioning( this IApplicationBuilder app )
20+
{
21+
Arg.NotNull( app, nameof( app ) );
22+
Contract.Ensures( Contract.Result<IApplicationBuilder>() != null );
23+
24+
app.UseMvc( builder => builder.Routes.Add( builder.ServiceProvider.GetRequiredService<IApiVersionRoutePolicy>() ) );
25+
return app;
26+
}
27+
}
28+
}

src/Microsoft.AspNetCore.Mvc.Versioning/Microsoft.Extensions.DependencyInjection/IServiceCollectionExtensions.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ public static IServiceCollection AddApiVersioning( this IServiceCollection servi
3939
setupAction( options );
4040
services.Add( new ServiceDescriptor( typeof( IApiVersionReader ), options.ApiVersionReader ) );
4141
services.Add( new ServiceDescriptor( typeof( IApiVersionSelector ), options.ApiVersionSelector ) );
42+
services.Add( new ServiceDescriptor( typeof( IErrorResponseProvider ), options.ErrorResponses ) );
4243
services.Add( Singleton<IOptions<ApiVersioningOptions>>( new OptionsWrapper<ApiVersioningOptions>( options ) ) );
4344
services.Replace( Singleton<IActionSelector, ApiVersionActionSelector>() );
45+
services.TryAddSingleton<IApiVersionRoutePolicy, DefaultApiVersionRoutePolicy>();
4446

4547
if ( options.ReportApiVersions )
4648
{
@@ -58,7 +60,7 @@ public static IServiceCollection AddApiVersioning( this IServiceCollection servi
5860
mvcOptions.Conventions.Add( new ApiVersionConvention( options.DefaultApiVersion, options.Conventions ) );
5961
} );
6062

61-
services.AddRouting( mvcOptions => mvcOptions.ConstraintMap.Add( "apiVersion", typeof( ApiVersionRouteConstraint ) ) );
63+
services.AddRouting( routeOptions => routeOptions.ConstraintMap.Add( "apiVersion", typeof( ApiVersionRouteConstraint ) ) );
6264

6365
return services;
6466
}

0 commit comments

Comments
 (0)