Removed MVC's custom request scope
We need to figure out a consistent way to throw errors when there isn't a request scope already setup.
This commit is contained in:
parent
b3d851dfe9
commit
c4f01b8ec9
|
|
@ -1,10 +1,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
|
@ -26,85 +23,49 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public async Task RouteAsync([NotNull] RouteContext context)
|
||||
{
|
||||
using (EnsureScopedServiceProvider(context.HttpContext))
|
||||
var services = context.HttpContext.RequestServices;
|
||||
Contract.Assert(services != null);
|
||||
|
||||
// TODO: Throw an error here that's descriptive enough so that
|
||||
// users understand they should call the per request scoped middleware
|
||||
// or set HttpContext.Services manually
|
||||
|
||||
var requestContext = new RequestContext(context.HttpContext, context.Values);
|
||||
|
||||
var actionSelector = services.GetService<IActionSelector>();
|
||||
var actionDescriptor = await actionSelector.SelectAsync(requestContext);
|
||||
if (actionDescriptor == null)
|
||||
{
|
||||
var services = context.HttpContext.RequestServices;
|
||||
Contract.Assert(services != null);
|
||||
|
||||
var requestContext = new RequestContext(context.HttpContext, context.Values);
|
||||
|
||||
var actionSelector = services.GetService<IActionSelector>();
|
||||
var actionDescriptor = await actionSelector.SelectAsync(requestContext);
|
||||
if (actionDescriptor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var actionContext = new ActionContext(context.HttpContext, context.Router, context.Values, actionDescriptor);
|
||||
|
||||
var contextAccessor = services.GetService<IContextAccessor<ActionContext>>();
|
||||
using (contextAccessor.SetContextSource(() => actionContext, PreventExchange))
|
||||
{
|
||||
var invokerFactory = services.GetService<IActionInvokerFactory>();
|
||||
var invoker = invokerFactory.CreateInvoker(actionContext);
|
||||
if (invoker == null)
|
||||
{
|
||||
var ex = new InvalidOperationException(
|
||||
Resources.FormatActionInvokerFactory_CouldNotCreateInvoker(actionDescriptor));
|
||||
|
||||
// Add tracing/logging (what do we think of this pattern of tacking on extra data on the exception?)
|
||||
ex.Data.Add("AD", actionDescriptor);
|
||||
|
||||
throw ex;
|
||||
}
|
||||
|
||||
await invoker.InvokeActionAsync();
|
||||
|
||||
context.IsHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IDisposable EnsureScopedServiceProvider([NotNull] HttpContext httpContext)
|
||||
{
|
||||
if (httpContext.RequestServices != null)
|
||||
{
|
||||
// There's already a request-scope, we don't need to create one. It's safe to return null
|
||||
// here, and that makes sure that we don't accidentally dispose the scope.
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
var applicationServices = httpContext.ApplicationServices;
|
||||
var actionContext = new ActionContext(context.HttpContext, context.Router, context.Values, actionDescriptor);
|
||||
|
||||
var scopeFactory = applicationServices.GetService<IServiceScopeFactory>();
|
||||
var scope = scopeFactory.CreateScope();
|
||||
var contextAccessor = services.GetService<IContextAccessor<ActionContext>>();
|
||||
using (contextAccessor.SetContextSource(() => actionContext, PreventExchange))
|
||||
{
|
||||
var invokerFactory = services.GetService<IActionInvokerFactory>();
|
||||
var invoker = invokerFactory.CreateInvoker(actionContext);
|
||||
if (invoker == null)
|
||||
{
|
||||
var ex = new InvalidOperationException(
|
||||
Resources.FormatActionInvokerFactory_CouldNotCreateInvoker(actionDescriptor));
|
||||
|
||||
var scopeHolder = new ScopeHolder(httpContext, scope);
|
||||
httpContext.RequestServices = scope.ServiceProvider;
|
||||
return scopeHolder;
|
||||
// Add tracing/logging (what do we think of this pattern of tacking on extra data on the exception?)
|
||||
ex.Data.Add("AD", actionDescriptor);
|
||||
|
||||
throw ex;
|
||||
}
|
||||
|
||||
await invoker.InvokeActionAsync();
|
||||
|
||||
context.IsHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private ActionContext PreventExchange(ActionContext contex)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.ActionContextAccessor_SetValueNotSupported);
|
||||
}
|
||||
|
||||
private class ScopeHolder : IDisposable
|
||||
{
|
||||
private readonly HttpContext _httpContext;
|
||||
private readonly IServiceScope _scope;
|
||||
|
||||
public ScopeHolder([NotNull] HttpContext httpContext, [NotNull] IServiceScope scope)
|
||||
{
|
||||
_httpContext = httpContext;
|
||||
_scope = scope;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_httpContext.RequestServices = null;
|
||||
_scope.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue