Skip to content

Commit e1bfd2c

Browse files
Add extension method to initialize IApiVersioningFeature on demand. Fixes #704
1 parent 825d93c commit e1bfd2c

13 files changed

+34
-20
lines changed

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,36 @@
1111
public static class HttpContextExtensions
1212
{
1313
/// <summary>
14-
/// Gets the current API version requested.
14+
/// Gets the API versioning feature associated with the current HTTP context.
1515
/// </summary>
16-
/// <param name="context">The current <see cref="HttpContext">HTTP context</see> to get the API version for.</param>
17-
/// <returns>The requested <see cref="ApiVersion">API version</see> or <c>null</c>.</returns>
18-
/// <remarks>This method will return <c>null</c> no service API version was requested or the requested
19-
/// service API version is in an invalid format.</remarks>
20-
/// <exception cref="AmbiguousApiVersionException">Multiple, different API versions were requested.</exception>
21-
public static ApiVersion? GetRequestedApiVersion( this HttpContext context )
16+
/// <param name="context">The current <see cref="HttpContext">HTTP context</see> to get the API feature for.</param>
17+
/// <returns>The current <see cref="IApiVersioningFeature">API versioning feature</see>.</returns>
18+
public static IApiVersioningFeature ApiVersioningFeature( this HttpContext context )
2219
{
2320
if ( context == null )
2421
{
2522
throw new ArgumentNullException( nameof( context ) );
2623
}
2724

2825
var feature = context.Features.Get<IApiVersioningFeature>();
29-
return feature?.RequestedApiVersion;
26+
27+
if ( feature == null )
28+
{
29+
feature = new ApiVersioningFeature( context );
30+
context.Features.Set( feature );
31+
}
32+
33+
return feature;
3034
}
35+
36+
/// <summary>
37+
/// Gets the current API version requested.
38+
/// </summary>
39+
/// <param name="context">The current <see cref="HttpContext">HTTP context</see> to get the API version for.</param>
40+
/// <returns>The requested <see cref="ApiVersion">API version</see> or <c>null</c>.</returns>
41+
/// <remarks>This method will return <c>null</c> no service API version was requested or the requested
42+
/// service API version is in an invalid format.</remarks>
43+
/// <exception cref="AmbiguousApiVersionException">Multiple, different API versions were requested.</exception>
44+
public static ApiVersion? GetRequestedApiVersion( this HttpContext context ) => context.ApiVersioningFeature().RequestedApiVersion;
3145
}
3246
}

src/Microsoft.AspNetCore.Mvc.Versioning/Routing/ApiVersionLinkGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static void AddApiVersionRouteValueIfNecessary( HttpContext httpContext, RouteVa
8383
throw new ArgumentNullException( nameof( values ) );
8484
}
8585

86-
var feature = httpContext.Features.Get<IApiVersioningFeature>();
86+
var feature = httpContext.ApiVersioningFeature();
8787
var key = feature.RouteParameter;
8888

8989
if ( string.IsNullOrEmpty( key ) )

src/Microsoft.AspNetCore.Mvc.Versioning/Routing/ApiVersionMatcherPolicy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public Task ApplyAsync( HttpContext httpContext, CandidateSet candidates )
9393
if ( apiVersion == null && Options.AssumeDefaultVersionWhenUnspecified )
9494
{
9595
apiVersion = TrySelectApiVersion( httpContext, candidates );
96-
httpContext.Features.Get<IApiVersioningFeature>().RequestedApiVersion = apiVersion;
96+
httpContext.ApiVersioningFeature().RequestedApiVersion = apiVersion;
9797
}
9898

9999
var (matched, hasCandidates) = MatchApiVersion( candidates, apiVersion );

src/Microsoft.AspNetCore.Mvc.Versioning/Routing/ApiVersionRouteConstraint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public bool Match( HttpContext? httpContext, IRouter? route, string routeKey, Ro
5050
throw new ArgumentNullException( nameof( httpContext ) );
5151
}
5252

53-
var feature = httpContext.Features.Get<IApiVersioningFeature>();
53+
var feature = httpContext.ApiVersioningFeature();
5454

5555
feature.RouteParameter = routeKey;
5656
feature.RawRequestedApiVersion = value;

src/Microsoft.AspNetCore.Mvc.Versioning/Routing/ApiVersionUrlHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public ApiVersionUrlHelper( ActionContext actionContext, IUrlHelper url )
2121
{
2222
ActionContext = actionContext ?? throw new ArgumentNullException( nameof( actionContext ) );
2323
Url = url;
24-
feature = actionContext.HttpContext.Features.Get<IApiVersioningFeature>();
24+
feature = actionContext.HttpContext.ApiVersioningFeature();
2525
}
2626

2727
/// <summary>

src/Microsoft.AspNetCore.Mvc.Versioning/Routing/CatchAllRouteHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ sealed class CatchAllRouteHandler : IRouter
1717
/// <inheritdoc />
1818
public Task RouteAsync( RouteContext context )
1919
{
20-
var feature = context.HttpContext.Features.Get<IApiVersioningFeature>();
20+
var feature = context.HttpContext.ApiVersioningFeature();
2121
routePolicy.Evaluate( context, feature.SelectionResult );
2222
return CompletedTask;
2323
}

src/Microsoft.AspNetCore.Mvc.Versioning/Routing/ClientErrorBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ sealed class ClientErrorBuilder
3131

3232
internal RequestHandler Build()
3333
{
34-
var feature = HttpContext!.Features.Get<IApiVersioningFeature>();
34+
var feature = HttpContext!.ApiVersioningFeature();
3535
var request = HttpContext!.Request;
3636
var method = request.Method;
3737
var requestedVersion = feature.RawRequestedApiVersion;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public virtual IReadOnlyList<ActionDescriptor> SelectCandidates( RouteContext co
158158

159159
var selectionContext = new ActionSelectionContext( httpContext, matches, apiVersion );
160160
var finalMatches = SelectBestActions( selectionContext );
161-
var feature = httpContext.Features.Get<IApiVersioningFeature>();
161+
var feature = httpContext.ApiVersioningFeature();
162162
var selectionResult = feature.SelectionResult;
163163

164164
feature.RequestedApiVersion = selectionContext.RequestedVersion;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public virtual Task BindModelAsync( ModelBindingContext bindingContext )
2020
throw new ArgumentNullException( nameof( bindingContext ) );
2121
}
2222

23-
var feature = bindingContext.HttpContext.Features.Get<IApiVersioningFeature>();
23+
var feature = bindingContext.HttpContext.ApiVersioningFeature();
2424
var model = feature.RequestedApiVersion;
2525

2626
if ( model != null )

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public partial class UrlSegmentApiVersionReader
2828
}
2929

3030
reentrant = true;
31-
var feature = request.HttpContext.Features.Get<IApiVersioningFeature>();
31+
var feature = request.HttpContext.ApiVersioningFeature();
3232
var value = feature.RawRequestedApiVersion;
3333
reentrant = false;
3434

src/Microsoft.AspNetCore.OData.Versioning/AspNet.OData/Routing/VersionedAttributeRoutingConvention.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ protected virtual ApiVersion SelectApiVersion( RouteContext routeContext )
145145
}
146146

147147
var httpContext = routeContext.HttpContext;
148-
var feature = httpContext.Features.Get<IApiVersioningFeature>();
148+
var feature = httpContext.ApiVersioningFeature();
149149
ApiVersion? version;
150150

151151
try

src/Microsoft.AspNetCore.OData.Versioning/AspNet.OData/Routing/VersionedMetadataRoutingConvention.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public class VersionedMetadataRoutingConvention : IODataRoutingConvention
4747
}
4848

4949
var context = request.HttpContext;
50-
var feature = context.Features.Get<IApiVersioningFeature>();
50+
var feature = context.ApiVersioningFeature();
5151
string? apiVersion;
5252

5353
try

src/Microsoft.AspNetCore.OData.Versioning/AspNetCore.Mvc/Versioning/ODataApiVersionActionSelector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public override IReadOnlyList<ActionDescriptor> SelectCandidates( RouteContext c
197197
}
198198
}
199199

200-
var feature = httpContext.Features.Get<IApiVersioningFeature>();
200+
var feature = httpContext.ApiVersioningFeature();
201201
var selectionResult = feature.SelectionResult;
202202

203203
feature.RequestedApiVersion = selectionContext.RequestedVersion;

0 commit comments

Comments
 (0)