[Fixes #4294] TypeActivate MvcRouteHandler
This commit is contained in:
parent
b96851ec20
commit
3d0f436a06
|
|
@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Builder
|
|||
|
||||
var routes = new RouteBuilder(app)
|
||||
{
|
||||
DefaultHandler = new MvcRouteHandler(),
|
||||
DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
|
||||
};
|
||||
|
||||
configureRoutes(routes);
|
||||
|
|
|
|||
|
|
@ -207,6 +207,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddSingleton(ArrayPool<byte>.Shared);
|
||||
services.TryAddSingleton(ArrayPool<char>.Shared);
|
||||
services.TryAddSingleton<ObjectResultExecutor>();
|
||||
|
||||
//
|
||||
// Setup default handler
|
||||
//
|
||||
services.TryAddSingleton<MvcRouteHandler>();
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultServices(IServiceCollection services)
|
||||
|
|
|
|||
|
|
@ -10,21 +10,44 @@ using Microsoft.AspNetCore.Mvc.Core;
|
|||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class MvcRouteHandler : IRouter
|
||||
{
|
||||
private bool _servicesRetrieved;
|
||||
|
||||
private IActionContextAccessor _actionContextAccessor;
|
||||
private IActionInvokerFactory _actionInvokerFactory;
|
||||
private IActionSelector _actionSelector;
|
||||
private ILogger _logger;
|
||||
private DiagnosticSource _diagnosticSource;
|
||||
|
||||
public MvcRouteHandler(
|
||||
IActionInvokerFactory actionInvokerFactory,
|
||||
IActionSelector actionSelector,
|
||||
DiagnosticSource diagnosticSource,
|
||||
ILoggerFactory loggerFactory)
|
||||
: this(actionInvokerFactory, actionSelector, diagnosticSource, loggerFactory, actionContextAccessor: null)
|
||||
{
|
||||
}
|
||||
|
||||
public MvcRouteHandler(
|
||||
IActionInvokerFactory actionInvokerFactory,
|
||||
IActionSelector actionSelector,
|
||||
DiagnosticSource diagnosticSource,
|
||||
ILoggerFactory loggerFactory,
|
||||
IActionContextAccessor actionContextAccessor)
|
||||
{
|
||||
// The IActionContextAccessor is optional. We want to avoid the overhead of using CallContext
|
||||
// if possible.
|
||||
_actionContextAccessor = actionContextAccessor;
|
||||
|
||||
_actionInvokerFactory = actionInvokerFactory;
|
||||
_actionSelector = actionSelector;
|
||||
_diagnosticSource = diagnosticSource;
|
||||
_logger = loggerFactory.CreateLogger<MvcRouteHandler>();
|
||||
}
|
||||
|
||||
public VirtualPathData GetVirtualPath(VirtualPathContext context)
|
||||
{
|
||||
if (context == null)
|
||||
|
|
@ -43,8 +66,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
EnsureServices(context.HttpContext);
|
||||
|
||||
var actionDescriptor = _actionSelector.Select(context);
|
||||
if (actionDescriptor == null)
|
||||
{
|
||||
|
|
@ -107,28 +128,5 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
_diagnosticSource.AfterAction(actionDescriptor, httpContext, routeData);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureServices(HttpContext context)
|
||||
{
|
||||
if (_servicesRetrieved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var services = context.RequestServices;
|
||||
|
||||
// The IActionContextAccessor is optional. We want to avoid the overhead of using CallContext
|
||||
// if possible.
|
||||
_actionContextAccessor = services.GetService<IActionContextAccessor>();
|
||||
|
||||
_actionInvokerFactory = services.GetRequiredService<IActionInvokerFactory>();
|
||||
_actionSelector = services.GetRequiredService<IActionSelector>();
|
||||
_diagnosticSource = services.GetRequiredService<DiagnosticSource>();
|
||||
|
||||
var factory = services.GetRequiredService<ILoggerFactory>();
|
||||
_logger = factory.CreateLogger<MvcRouteHandler>();
|
||||
|
||||
_servicesRetrieved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
.SetupGet(ad => ad.DisplayName)
|
||||
.Returns(displayName);
|
||||
|
||||
var context = CreateRouteContext(actionDescriptor: actionDescriptor.Object, loggerFactory: loggerFactory);
|
||||
var context = CreateRouteContext();
|
||||
|
||||
var handler = new MvcRouteHandler();
|
||||
var handler = CreateMvcRouteHandler(actionDescriptor: actionDescriptor.Object, loggerFactory: loggerFactory);
|
||||
await handler.RouteAsync(context);
|
||||
|
||||
// Act
|
||||
|
|
@ -62,11 +62,12 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
.Setup(a => a.Select(It.IsAny<RouteContext>()))
|
||||
.Returns<ActionDescriptor>(null);
|
||||
|
||||
var context = CreateRouteContext(
|
||||
var context = CreateRouteContext();
|
||||
|
||||
var handler = CreateMvcRouteHandler(
|
||||
actionSelector: mockActionSelector.Object,
|
||||
loggerFactory: loggerFactory);
|
||||
|
||||
var handler = new MvcRouteHandler();
|
||||
var expectedMessage = "No actions matched the current request";
|
||||
|
||||
// Act
|
||||
|
|
@ -95,8 +96,8 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
return invoker.Object;
|
||||
});
|
||||
|
||||
var context = CreateRouteContext(invokerFactory: invokerFactory.Object);
|
||||
var handler = new MvcRouteHandler();
|
||||
var context = CreateRouteContext();
|
||||
var handler = CreateMvcRouteHandler(invokerFactory: invokerFactory.Object);
|
||||
|
||||
var originalRouteData = context.RouteData;
|
||||
originalRouteData.Values.Add(TreeRouter.RouteGroupKey, "/Home/Test");
|
||||
|
|
@ -117,10 +118,10 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
// Arrange
|
||||
var listener = new TestDiagnosticListener();
|
||||
|
||||
var context = CreateRouteContext(diagnosticListener: listener);
|
||||
var context = CreateRouteContext();
|
||||
context.RouteData.Values.Add("tag", "value");
|
||||
|
||||
var handler = new MvcRouteHandler();
|
||||
var handler = CreateMvcRouteHandler(diagnosticListener: listener);
|
||||
await handler.RouteAsync(context);
|
||||
|
||||
// Act
|
||||
|
|
@ -143,9 +144,9 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
// Arrange
|
||||
var listener = new TestDiagnosticListener();
|
||||
|
||||
var context = CreateRouteContext(diagnosticListener: listener);
|
||||
var context = CreateRouteContext();
|
||||
|
||||
var handler = new MvcRouteHandler();
|
||||
var handler = CreateMvcRouteHandler(diagnosticListener: listener);
|
||||
await handler.RouteAsync(context);
|
||||
|
||||
// Act
|
||||
|
|
@ -156,14 +157,15 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
Assert.NotNull(listener.AfterAction?.HttpContext);
|
||||
}
|
||||
|
||||
private RouteContext CreateRouteContext(
|
||||
private MvcRouteHandler CreateMvcRouteHandler(
|
||||
ActionDescriptor actionDescriptor = null,
|
||||
IActionSelector actionSelector = null,
|
||||
IActionInvokerFactory invokerFactory = null,
|
||||
ILoggerFactory loggerFactory = null,
|
||||
IOptions<MvcOptions> optionsAccessor = null,
|
||||
object diagnosticListener = null)
|
||||
{
|
||||
var actionContextAccessor = new ActionContextAccessor();
|
||||
|
||||
if (actionDescriptor == null)
|
||||
{
|
||||
var mockAction = new Mock<ActionDescriptor>();
|
||||
|
|
@ -175,10 +177,20 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
var mockActionSelector = new Mock<IActionSelector>();
|
||||
mockActionSelector.Setup(a => a.Select(It.IsAny<RouteContext>()))
|
||||
.Returns(actionDescriptor);
|
||||
|
||||
actionSelector = mockActionSelector.Object;
|
||||
}
|
||||
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
loggerFactory = NullLoggerFactory.Instance;
|
||||
}
|
||||
|
||||
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
|
||||
if (diagnosticListener != null)
|
||||
{
|
||||
diagnosticSource.SubscribeWithAdapter(diagnosticListener);
|
||||
}
|
||||
|
||||
if (invokerFactory == null)
|
||||
{
|
||||
var mockInvoker = new Mock<IActionInvoker>();
|
||||
|
|
@ -192,46 +204,19 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
invokerFactory = mockInvokerFactory.Object;
|
||||
}
|
||||
|
||||
if (loggerFactory == null)
|
||||
{
|
||||
loggerFactory = NullLoggerFactory.Instance;
|
||||
}
|
||||
|
||||
if (optionsAccessor == null)
|
||||
{
|
||||
optionsAccessor = new TestOptionsManager<MvcOptions>();
|
||||
}
|
||||
|
||||
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
|
||||
if (diagnosticListener != null)
|
||||
{
|
||||
diagnosticSource.SubscribeWithAdapter(diagnosticListener);
|
||||
}
|
||||
return new MvcRouteHandler(
|
||||
invokerFactory,
|
||||
actionSelector,
|
||||
diagnosticSource,
|
||||
loggerFactory,
|
||||
actionContextAccessor);
|
||||
}
|
||||
|
||||
private RouteContext CreateRouteContext()
|
||||
{
|
||||
var routingFeature = new RoutingFeature();
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(IActionContextAccessor)))
|
||||
.Returns(new ActionContextAccessor());
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(IActionSelector)))
|
||||
.Returns(actionSelector);
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(IActionInvokerFactory)))
|
||||
.Returns(invokerFactory);
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(ILoggerFactory)))
|
||||
.Returns(loggerFactory);
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(MvcMarkerService)))
|
||||
.Returns(new MvcMarkerService());
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(IOptions<MvcOptions>)))
|
||||
.Returns(optionsAccessor);
|
||||
httpContext
|
||||
.Setup(h => h.RequestServices.GetService(typeof(DiagnosticSource)))
|
||||
.Returns(diagnosticSource);
|
||||
httpContext
|
||||
.Setup(h => h.Features[typeof(IRoutingFeature)])
|
||||
.Returns(routingFeature);
|
||||
|
|
|
|||
Loading…
Reference in New Issue