@@ -10,7 +10,6 @@ namespace Asp.Versioning.Builder;
1010using Microsoft . Extensions . DependencyInjection ;
1111using Microsoft . Extensions . Options ;
1212using System . Globalization ;
13- using System . Runtime . CompilerServices ;
1413using static Asp . Versioning . ApiVersionParameterLocation ;
1514using static Asp . Versioning . ApiVersionProviderOptions ;
1615
@@ -47,16 +46,20 @@ private static void Finialize( EndpointBuilder endpointBuilder, ApiVersionSet? v
4746
4847 endpointBuilder . Metadata . Add ( metadata ) ;
4948
50- var requestDelegate = default ( RequestDelegate ) ;
49+ var requestDelegate =
50+ endpointBuilder . RequestDelegate
51+ ?? throw new InvalidOperationException (
52+ string . Format (
53+ CultureInfo . CurrentCulture ,
54+ Format . UnsetRequestDelegate ,
55+ nameof ( RequestDelegate ) ,
56+ nameof ( RouteEndpoint ) ) ) ;
5157
5258 if ( reportApiVersions )
5359 {
54- requestDelegate = EnsureRequestDelegate ( requestDelegate , endpointBuilder . RequestDelegate ) ;
55-
5660 var reporter = services . GetRequiredService < IReportApiVersions > ( ) ;
5761
5862 requestDelegate = new ReportApiVersionsDecorator ( requestDelegate , reporter , metadata ) ;
59- endpointBuilder . RequestDelegate = requestDelegate ;
6063 }
6164
6265 var parameterSource = services . GetRequiredService < IApiVersionParameterSource > ( ) ;
@@ -67,11 +70,15 @@ private static void Finialize( EndpointBuilder endpointBuilder, ApiVersionSet? v
6770
6871 if ( ! string . IsNullOrEmpty ( parameterName ) )
6972 {
70- requestDelegate = EnsureRequestDelegate ( requestDelegate , endpointBuilder . RequestDelegate ) ;
7173 requestDelegate = new ContentTypeApiVersionDecorator ( requestDelegate , parameterName ) ;
72- endpointBuilder . RequestDelegate = requestDelegate ;
7374 }
7475 }
76+
77+ endpointBuilder . RequestDelegate = context =>
78+ {
79+ context . RequestServices = new InjectApiVersion ( context ) ;
80+ return requestDelegate ( context ) ;
81+ } ;
7582 }
7683
7784 private static bool IsApiVersionNeutral ( IList < object > metadata )
@@ -261,16 +268,6 @@ private static ApiVersionMetadata Build( IList<object> metadata, ApiVersionSet v
261268 return new ( apiModel , endpointModel , name ) ;
262269 }
263270
264- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
265- private static RequestDelegate EnsureRequestDelegate ( RequestDelegate ? current , RequestDelegate ? original ) =>
266- ( current ?? original ) ??
267- throw new InvalidOperationException (
268- string . Format (
269- CultureInfo . CurrentCulture ,
270- Format . UnsetRequestDelegate ,
271- nameof ( RequestDelegate ) ,
272- nameof ( RouteEndpoint ) ) ) ;
273-
274271 private record struct ApiVersionBuckets (
275272 IReadOnlyList < ApiVersion > Mapped ,
276273 IReadOnlyList < ApiVersion > Supported ,
@@ -284,4 +281,28 @@ private record struct ApiVersionBuckets(
284281 && Advertised . Count == 0
285282 && AdvertisedDeprecated . Count == 0 ;
286283 }
284+
285+ private sealed class InjectApiVersion : IServiceProvider
286+ {
287+ private static readonly Type ApiVersionType = typeof ( ApiVersion ) ;
288+ private readonly IServiceProvider provider ;
289+ private readonly HttpContext context ;
290+
291+ public InjectApiVersion ( HttpContext context )
292+ {
293+ this . context = context ;
294+ provider = context . RequestServices ;
295+ context . RequestServices = this ;
296+ }
297+
298+ public object ? GetService ( Type serviceType )
299+ {
300+ if ( serviceType . IsAssignableFrom ( ApiVersionType ) )
301+ {
302+ return context . RequestedApiVersion ;
303+ }
304+
305+ return provider . GetService ( serviceType ) ;
306+ }
307+ }
287308}
0 commit comments