diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesContainerMiddleware.cs b/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesContainerMiddleware.cs index 6b326d509d..8f30c3195c 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesContainerMiddleware.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesContainerMiddleware.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; @@ -12,7 +13,7 @@ namespace Microsoft.AspNetCore.Hosting.Internal public class RequestServicesContainerMiddleware { private readonly RequestDelegate _next; - private IServiceScopeFactory _scopeFactory; + private readonly IServiceScopeFactory _scopeFactory; public RequestServicesContainerMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory) { @@ -25,37 +26,37 @@ namespace Microsoft.AspNetCore.Hosting.Internal throw new ArgumentNullException(nameof(scopeFactory)); } - _scopeFactory = scopeFactory; _next = next; + _scopeFactory = scopeFactory; } public async Task Invoke(HttpContext httpContext) { - if (httpContext == null) - { - throw new ArgumentNullException(nameof(httpContext)); - } + Debug.Assert(httpContext != null); - var existingFeature = httpContext.Features.Get(); + // local cache for virtual disptach result + var features = httpContext.Features; + var existingFeature = features.Get(); - // All done if request services is set + // All done if RequestServices is set if (existingFeature?.RequestServices != null) { await _next.Invoke(httpContext); return; } - using (var feature = new RequestServicesFeature(_scopeFactory)) + var replacementFeature = new RequestServicesFeature(_scopeFactory); + + try { - try - { - httpContext.Features.Set(feature); - await _next.Invoke(httpContext); - } - finally - { - httpContext.Features.Set(existingFeature); - } + features.Set(replacementFeature); + await _next.Invoke(httpContext); + } + finally + { + replacementFeature.Dispose(); + // Restore previous feature state + features.Set(existingFeature); } } } diff --git a/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesFeature.cs b/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesFeature.cs index f1d0a86385..8d85cec63e 100644 --- a/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesFeature.cs +++ b/src/Microsoft.AspNetCore.Hosting/Internal/RequestServicesFeature.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.DependencyInjection; @@ -9,18 +10,14 @@ namespace Microsoft.AspNetCore.Hosting.Internal { public class RequestServicesFeature : IServiceProvidersFeature, IDisposable { - private IServiceScopeFactory _scopeFactory; + private readonly IServiceScopeFactory _scopeFactory; private IServiceProvider _requestServices; private IServiceScope _scope; private bool _requestServicesSet; public RequestServicesFeature(IServiceScopeFactory scopeFactory) { - if (scopeFactory == null) - { - throw new ArgumentNullException(nameof(scopeFactory)); - } - + Debug.Assert(scopeFactory != null); _scopeFactory = scopeFactory; }