Add more event notification data points
Also includes some cleanup of the testing code that we're using with proxies.
This commit is contained in:
parent
07fabde92a
commit
e384938425
|
|
@ -10,6 +10,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.Notification;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Core
|
namespace Microsoft.AspNet.Mvc.Core
|
||||||
{
|
{
|
||||||
|
|
@ -32,6 +33,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
||||||
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
|
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
|
||||||
[NotNull] ILogger logger,
|
[NotNull] ILogger logger,
|
||||||
|
[NotNull] INotifier notifier,
|
||||||
int maxModelValidationErrors)
|
int maxModelValidationErrors)
|
||||||
: base(
|
: base(
|
||||||
actionContext,
|
actionContext,
|
||||||
|
|
@ -43,6 +45,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
valueProviderFactories,
|
valueProviderFactories,
|
||||||
actionBindingContextAccessor,
|
actionBindingContextAccessor,
|
||||||
logger,
|
logger,
|
||||||
|
notifier,
|
||||||
maxModelValidationErrors)
|
maxModelValidationErrors)
|
||||||
{
|
{
|
||||||
_descriptor = descriptor;
|
_descriptor = descriptor;
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.Notification;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Core
|
namespace Microsoft.AspNet.Mvc.Core
|
||||||
|
|
@ -24,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
|
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
|
||||||
private readonly int _maxModelValidationErrors;
|
private readonly int _maxModelValidationErrors;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly INotifier _notifier;
|
||||||
|
|
||||||
public ControllerActionInvokerProvider(
|
public ControllerActionInvokerProvider(
|
||||||
IControllerFactory controllerFactory,
|
IControllerFactory controllerFactory,
|
||||||
|
|
@ -31,7 +33,8 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
IControllerActionArgumentBinder argumentBinder,
|
IControllerActionArgumentBinder argumentBinder,
|
||||||
IOptions<MvcOptions> optionsAccessor,
|
IOptions<MvcOptions> optionsAccessor,
|
||||||
IActionBindingContextAccessor actionBindingContextAccessor,
|
IActionBindingContextAccessor actionBindingContextAccessor,
|
||||||
ILoggerFactory loggerFactory)
|
ILoggerFactory loggerFactory,
|
||||||
|
INotifier notifier)
|
||||||
{
|
{
|
||||||
_controllerFactory = controllerFactory;
|
_controllerFactory = controllerFactory;
|
||||||
_filterProviders = filterProviders.OrderBy(item => item.Order).ToArray();
|
_filterProviders = filterProviders.OrderBy(item => item.Order).ToArray();
|
||||||
|
|
@ -43,8 +46,8 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
_valueProviderFactories = optionsAccessor.Options.ValueProviderFactories.ToArray();
|
_valueProviderFactories = optionsAccessor.Options.ValueProviderFactories.ToArray();
|
||||||
_actionBindingContextAccessor = actionBindingContextAccessor;
|
_actionBindingContextAccessor = actionBindingContextAccessor;
|
||||||
_maxModelValidationErrors = optionsAccessor.Options.MaxModelValidationErrors;
|
_maxModelValidationErrors = optionsAccessor.Options.MaxModelValidationErrors;
|
||||||
|
|
||||||
_logger = loggerFactory.CreateLogger<ControllerActionInvoker>();
|
_logger = loggerFactory.CreateLogger<ControllerActionInvoker>();
|
||||||
|
_notifier = notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Order
|
public int Order
|
||||||
|
|
@ -72,6 +75,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
_valueProviderFactories,
|
_valueProviderFactories,
|
||||||
_actionBindingContextAccessor,
|
_actionBindingContextAccessor,
|
||||||
_logger,
|
_logger,
|
||||||
|
_notifier,
|
||||||
_maxModelValidationErrors);
|
_maxModelValidationErrors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.Notification;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Core
|
namespace Microsoft.AspNet.Mvc.Core
|
||||||
{
|
{
|
||||||
|
|
@ -24,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
|
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
|
||||||
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
|
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly INotifier _notifier;
|
||||||
private readonly int _maxModelValidationErrors;
|
private readonly int _maxModelValidationErrors;
|
||||||
|
|
||||||
private IFilterMetadata[] _filters;
|
private IFilterMetadata[] _filters;
|
||||||
|
|
@ -63,6 +65,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
||||||
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
|
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
|
||||||
[NotNull] ILogger logger,
|
[NotNull] ILogger logger,
|
||||||
|
[NotNull] INotifier notifier,
|
||||||
int maxModelValidationErrors)
|
int maxModelValidationErrors)
|
||||||
{
|
{
|
||||||
ActionContext = actionContext;
|
ActionContext = actionContext;
|
||||||
|
|
@ -75,6 +78,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
_valueProviderFactories = valueProviderFactories;
|
_valueProviderFactories = valueProviderFactories;
|
||||||
_actionBindingContextAccessor = actionBindingContextAccessor;
|
_actionBindingContextAccessor = actionBindingContextAccessor;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_notifier = notifier;
|
||||||
_maxModelValidationErrors = maxModelValidationErrors;
|
_maxModelValidationErrors = maxModelValidationErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +131,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
Debug.Assert(_authorizationContext != null);
|
Debug.Assert(_authorizationContext != null);
|
||||||
if (_authorizationContext.Result != null)
|
if (_authorizationContext.Result != null)
|
||||||
{
|
{
|
||||||
await _authorizationContext.Result.ExecuteResultAsync(ActionContext);
|
await InvokeResultAsync(_authorizationContext.Result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,7 +285,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
ResourceFilterShortCircuitLogMessage,
|
ResourceFilterShortCircuitLogMessage,
|
||||||
item.FilterAsync.GetType().FullName);
|
item.FilterAsync.GetType().FullName);
|
||||||
|
|
||||||
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
|
await InvokeResultAsync(_resourceExecutingContext.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||||
|
|
@ -301,7 +305,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
|
|
||||||
_logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.Filter.GetType().FullName);
|
_logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.Filter.GetType().FullName);
|
||||||
|
|
||||||
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
|
await InvokeResultAsync(_resourceExecutingContext.Result);
|
||||||
|
|
||||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||||
{
|
{
|
||||||
|
|
@ -343,7 +347,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
{
|
{
|
||||||
// This means that exception filters returned a result to 'handle' an error.
|
// This means that exception filters returned a result to 'handle' an error.
|
||||||
// We're not interested in seeing the exception details since it was handled.
|
// We're not interested in seeing the exception details since it was handled.
|
||||||
await _exceptionContext.Result.ExecuteResultAsync(ActionContext);
|
await InvokeResultAsync(_exceptionContext.Result);
|
||||||
|
|
||||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||||
{
|
{
|
||||||
|
|
@ -558,12 +562,35 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// All action filters have run, execute the action method.
|
// All action filters have run, execute the action method.
|
||||||
|
IActionResult result = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeActionMethod"))
|
||||||
|
{
|
||||||
|
_notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.BeforeActionMethod",
|
||||||
|
new { actionContext = ActionContext, arguments = _actionExecutingContext.ActionArguments });
|
||||||
|
}
|
||||||
|
|
||||||
|
result = await InvokeActionAsync(_actionExecutingContext);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterActionMethod"))
|
||||||
|
{
|
||||||
|
_notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.AfterActionMethod",
|
||||||
|
new { actionContext = ActionContext, result });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_actionExecutedContext = new ActionExecutedContext(
|
_actionExecutedContext = new ActionExecutedContext(
|
||||||
_actionExecutingContext,
|
_actionExecutingContext,
|
||||||
_filters,
|
_filters,
|
||||||
Instance)
|
Instance)
|
||||||
{
|
{
|
||||||
Result = await InvokeActionAsync(_actionExecutingContext),
|
Result = result
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -683,7 +710,15 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await InvokeResultAsync();
|
_cursor.SetStage(FilterStage.ActionResult);
|
||||||
|
|
||||||
|
// The empty result is always flowed back as the 'executed' result
|
||||||
|
if (_resultExecutingContext.Result == null)
|
||||||
|
{
|
||||||
|
_resultExecutingContext.Result = new EmptyResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
await InvokeResultAsync(_resultExecutingContext.Result);
|
||||||
|
|
||||||
Debug.Assert(_resultExecutedContext == null);
|
Debug.Assert(_resultExecutedContext == null);
|
||||||
_resultExecutedContext = new ResultExecutedContext(
|
_resultExecutedContext = new ResultExecutedContext(
|
||||||
|
|
@ -708,17 +743,28 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
return _resultExecutedContext;
|
return _resultExecutedContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InvokeResultAsync()
|
private async Task InvokeResultAsync(IActionResult result)
|
||||||
{
|
{
|
||||||
_cursor.SetStage(FilterStage.ActionResult);
|
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeActionResult"))
|
||||||
|
|
||||||
// The empty result is always flowed back as the 'executed' result
|
|
||||||
if (_resultExecutingContext.Result == null)
|
|
||||||
{
|
{
|
||||||
_resultExecutingContext.Result = new EmptyResult();
|
_notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.BeforeActionResult",
|
||||||
|
new { actionContext = ActionContext, result });
|
||||||
}
|
}
|
||||||
|
|
||||||
await _resultExecutingContext.Result.ExecuteResultAsync(_resultExecutingContext);
|
try
|
||||||
|
{
|
||||||
|
await result.ExecuteResultAsync(ActionContext);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterActionResult"))
|
||||||
|
{
|
||||||
|
_notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.AfterActionResult",
|
||||||
|
new { actionContext = ActionContext, result });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum FilterStage
|
private enum FilterStage
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,10 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
context.RouteData = newRouteData;
|
context.RouteData = newRouteData;
|
||||||
|
|
||||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.ActionSelected"))
|
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeAction"))
|
||||||
{
|
{
|
||||||
_notifier.Notify(
|
_notifier.Notify(
|
||||||
"Microsoft.AspNet.Mvc.ActionSelected",
|
"Microsoft.AspNet.Mvc.BeforeAction",
|
||||||
new { actionDescriptor, httpContext = context.HttpContext, routeData = context.RouteData});
|
new { actionDescriptor, httpContext = context.HttpContext, routeData = context.RouteData});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,16 +84,16 @@ namespace Microsoft.AspNet.Mvc
|
||||||
await InvokeActionAsync(context, actionDescriptor);
|
await InvokeActionAsync(context, actionDescriptor);
|
||||||
context.IsHandled = true;
|
context.IsHandled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.ActionInvoked"))
|
|
||||||
{
|
|
||||||
_notifier.Notify(
|
|
||||||
"Microsoft.AspNet.Mvc.ActionInvoked",
|
|
||||||
new { actionDescriptor, httpContext = context.HttpContext });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterAction"))
|
||||||
|
{
|
||||||
|
_notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.AfterAction",
|
||||||
|
new { actionDescriptor, httpContext = context.HttpContext });
|
||||||
|
}
|
||||||
|
|
||||||
if (!context.IsHandled)
|
if (!context.IsHandled)
|
||||||
{
|
{
|
||||||
context.RouteData = oldRouteData;
|
context.RouteData = oldRouteData;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
using Microsoft.Framework.Notification;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
|
|
@ -55,17 +56,31 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async Task ExecuteResultAsync([NotNull] ActionContext context)
|
public override async Task ExecuteResultAsync([NotNull] ActionContext context)
|
||||||
{
|
{
|
||||||
var viewEngine = ViewEngine ??
|
var services = context.HttpContext.RequestServices;
|
||||||
context.HttpContext.RequestServices.GetRequiredService<ICompositeViewEngine>();
|
var viewEngine = ViewEngine ?? services.GetRequiredService<ICompositeViewEngine>();
|
||||||
|
|
||||||
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<ViewResult>>();
|
var logger = services.GetRequiredService<ILogger<ViewResult>>();
|
||||||
|
var notifier = services.GetRequiredService<INotifier>();
|
||||||
|
|
||||||
var options = context.HttpContext.RequestServices.GetRequiredService<IOptions<MvcViewOptions>>();
|
var options = services.GetRequiredService<IOptions<MvcViewOptions>>();
|
||||||
|
|
||||||
var viewName = ViewName ?? context.ActionDescriptor.Name;
|
var viewName = ViewName ?? context.ActionDescriptor.Name;
|
||||||
var viewEngineResult = viewEngine.FindView(context, viewName);
|
var viewEngineResult = viewEngine.FindView(context, viewName);
|
||||||
if(!viewEngineResult.Success)
|
if(!viewEngineResult.Success)
|
||||||
{
|
{
|
||||||
|
if (notifier.ShouldNotify("Microsoft.AspNet.Mvc.ViewResultViewNotFound"))
|
||||||
|
{
|
||||||
|
notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.ViewResultViewNotFound",
|
||||||
|
new
|
||||||
|
{
|
||||||
|
actionContext = context,
|
||||||
|
result = this,
|
||||||
|
viewName = viewName,
|
||||||
|
searchedLocations = viewEngineResult.SearchedLocations
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
logger.LogError(
|
logger.LogError(
|
||||||
"The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}",
|
"The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}",
|
||||||
viewName,
|
viewName,
|
||||||
|
|
@ -73,6 +88,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
}
|
}
|
||||||
|
|
||||||
var view = viewEngineResult.EnsureSuccessful().View;
|
var view = viewEngineResult.EnsureSuccessful().View;
|
||||||
|
if (notifier.ShouldNotify("Microsoft.AspNet.Mvc.ViewResultViewFound"))
|
||||||
|
{
|
||||||
|
notifier.Notify(
|
||||||
|
"Microsoft.AspNet.Mvc.ViewResultViewFound",
|
||||||
|
new { actionContext = context, result = this, viewName, view = view });
|
||||||
|
}
|
||||||
|
|
||||||
logger.LogVerbose("The view '{ViewName}' was found.", viewName);
|
logger.LogVerbose("The view '{ViewName}' was found.", viewName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ using Microsoft.AspNet.Testing;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Microsoft.Framework.Logging.Testing;
|
using Microsoft.Framework.Logging.Testing;
|
||||||
|
using Microsoft.Framework.Notification;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -2042,6 +2043,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
new IValueProviderFactory[0],
|
new IValueProviderFactory[0],
|
||||||
new ActionBindingContextAccessor(),
|
new ActionBindingContextAccessor(),
|
||||||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||||
|
new Notifier(new ProxyNotifierMethodAdapter()),
|
||||||
maxAllowedErrorsInModelState);
|
maxAllowedErrorsInModelState);
|
||||||
|
|
||||||
return invoker;
|
return invoker;
|
||||||
|
|
@ -2104,6 +2106,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
new IValueProviderFactory[0],
|
new IValueProviderFactory[0],
|
||||||
new ActionBindingContextAccessor(),
|
new ActionBindingContextAccessor(),
|
||||||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||||
|
new Notifier(new ProxyNotifierMethodAdapter()),
|
||||||
200);
|
200);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -2204,6 +2207,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
||||||
IActionBindingContextAccessor actionBindingContext,
|
IActionBindingContextAccessor actionBindingContext,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
|
INotifier notifier,
|
||||||
int maxAllowedErrorsInModelState)
|
int maxAllowedErrorsInModelState)
|
||||||
: base(
|
: base(
|
||||||
actionContext,
|
actionContext,
|
||||||
|
|
@ -2218,6 +2222,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
valueProviderFactories,
|
valueProviderFactories,
|
||||||
actionBindingContext,
|
actionBindingContext,
|
||||||
logger,
|
logger,
|
||||||
|
notifier,
|
||||||
maxAllowedErrorsInModelState)
|
maxAllowedErrorsInModelState)
|
||||||
{
|
{
|
||||||
ControllerFactory = controllerFactory;
|
ControllerFactory = controllerFactory;
|
||||||
|
|
|
||||||
|
|
@ -169,10 +169,10 @@ namespace Microsoft.AspNet.Mvc
|
||||||
await handler.RouteAsync(context);
|
await handler.RouteAsync(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(listener?.ActionSelected.ActionDescriptor);
|
Assert.NotNull(listener.BeforeAction?.ActionDescriptor);
|
||||||
Assert.NotNull(listener?.ActionSelected.HttpContext);
|
Assert.NotNull(listener.BeforeAction?.HttpContext);
|
||||||
|
|
||||||
var routeValues = listener?.ActionSelected?.RouteData?.Values;
|
var routeValues = listener.BeforeAction?.RouteData?.Values;
|
||||||
Assert.NotNull(routeValues);
|
Assert.NotNull(routeValues);
|
||||||
|
|
||||||
Assert.Equal(1, routeValues.Count);
|
Assert.Equal(1, routeValues.Count);
|
||||||
|
|
@ -193,8 +193,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
await handler.RouteAsync(context);
|
await handler.RouteAsync(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(listener?.ActionInvoked.ActionDescriptor);
|
Assert.NotNull(listener.AfterAction?.ActionDescriptor);
|
||||||
Assert.NotNull(listener?.ActionInvoked.HttpContext);
|
Assert.NotNull(listener.AfterAction?.HttpContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RouteContext CreateRouteContext(
|
private RouteContext CreateRouteContext(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
|
{
|
||||||
|
public interface IProxyActionContext
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
|
{
|
||||||
|
public interface IProxyActionDescriptor
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
|
{
|
||||||
|
public interface IProxyActionResult
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
{
|
{
|
||||||
public interface IActionDescriptor
|
public interface IProxyHttpContext
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
{
|
{
|
||||||
public interface IRouteData
|
public interface IProxyRouteData
|
||||||
{
|
{
|
||||||
IReadOnlyList<object> Routers { get; }
|
IReadOnlyList<object> Routers { get; }
|
||||||
IDictionary<string, object> DataTokens { get; }
|
IDictionary<string, object> DataTokens { get; }
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
{
|
{
|
||||||
public interface IHttpContext
|
public interface IProxyView
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,29 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using Microsoft.Framework.Notification;
|
using Microsoft.Framework.Notification;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
{
|
{
|
||||||
public class TestNotificationListener
|
public class TestNotificationListener
|
||||||
{
|
{
|
||||||
public OnActionSelectedEventData ActionSelected { get; set; }
|
public class OnBeforeActionEventData
|
||||||
|
|
||||||
[NotificationName("Microsoft.AspNet.Mvc.ActionSelected")]
|
|
||||||
public virtual void OnActionSelected(
|
|
||||||
IHttpContext httpContext,
|
|
||||||
IRouteData routeData,
|
|
||||||
IActionDescriptor actionDescriptor)
|
|
||||||
{
|
{
|
||||||
ActionSelected = new OnActionSelectedEventData()
|
public IProxyActionDescriptor ActionDescriptor { get; set; }
|
||||||
|
public IProxyHttpContext HttpContext { get; set; }
|
||||||
|
public IProxyRouteData RouteData { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnBeforeActionEventData BeforeAction { get; set; }
|
||||||
|
|
||||||
|
[NotificationName("Microsoft.AspNet.Mvc.BeforeAction")]
|
||||||
|
public virtual void OnBeforeAction(
|
||||||
|
IProxyHttpContext httpContext,
|
||||||
|
IProxyRouteData routeData,
|
||||||
|
IProxyActionDescriptor actionDescriptor)
|
||||||
|
{
|
||||||
|
BeforeAction = new OnBeforeActionEventData()
|
||||||
{
|
{
|
||||||
ActionDescriptor = actionDescriptor,
|
ActionDescriptor = actionDescriptor,
|
||||||
HttpContext = httpContext,
|
HttpContext = httpContext,
|
||||||
|
|
@ -23,31 +31,76 @@ namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnActionInvokedEventData ActionInvoked { get; set; }
|
public class OnAfterActionEventData
|
||||||
|
|
||||||
[NotificationName("Microsoft.AspNet.Mvc.ActionInvoked")]
|
|
||||||
public virtual void OnActionInvoked(
|
|
||||||
IHttpContext httpContext,
|
|
||||||
IActionDescriptor actionDescriptor)
|
|
||||||
{
|
{
|
||||||
ActionInvoked = new OnActionInvokedEventData()
|
public IProxyActionDescriptor ActionDescriptor { get; set; }
|
||||||
|
public IProxyHttpContext HttpContext { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnAfterActionEventData AfterAction { get; set; }
|
||||||
|
|
||||||
|
[NotificationName("Microsoft.AspNet.Mvc.AfterAction")]
|
||||||
|
public virtual void OnAfterAction(
|
||||||
|
IProxyHttpContext httpContext,
|
||||||
|
IProxyActionDescriptor actionDescriptor)
|
||||||
|
{
|
||||||
|
AfterAction = new OnAfterActionEventData()
|
||||||
{
|
{
|
||||||
ActionDescriptor = actionDescriptor,
|
ActionDescriptor = actionDescriptor,
|
||||||
HttpContext = httpContext,
|
HttpContext = httpContext,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OnActionSelectedEventData
|
public class OnViewResultViewFoundEventData
|
||||||
{
|
{
|
||||||
public IActionDescriptor ActionDescriptor { get; set; }
|
public IProxyActionContext ActionContext { get; set; }
|
||||||
public IHttpContext HttpContext { get; set; }
|
public IProxyActionResult Result { get; set; }
|
||||||
public IRouteData RouteData { get; set; }
|
public string ViewName { get; set; }
|
||||||
|
public IProxyView View { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OnActionInvokedEventData
|
public OnViewResultViewFoundEventData ViewResultViewFound { get; set; }
|
||||||
|
|
||||||
|
[NotificationName("Microsoft.AspNet.Mvc.ViewResultViewFound")]
|
||||||
|
public virtual void OnViewResultViewFound(
|
||||||
|
IProxyActionContext actionContext,
|
||||||
|
IProxyActionResult result,
|
||||||
|
string viewName,
|
||||||
|
IProxyView view)
|
||||||
{
|
{
|
||||||
public IActionDescriptor ActionDescriptor { get; set; }
|
ViewResultViewFound = new OnViewResultViewFoundEventData()
|
||||||
public IHttpContext HttpContext { get; set; }
|
{
|
||||||
|
ActionContext = actionContext,
|
||||||
|
Result = result,
|
||||||
|
ViewName = viewName,
|
||||||
|
View = view,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OnViewResultViewNotFoundEventData
|
||||||
|
{
|
||||||
|
public IProxyActionContext ActionContext { get; set; }
|
||||||
|
public IProxyActionResult Result { get; set; }
|
||||||
|
public string ViewName { get; set; }
|
||||||
|
public IEnumerable<string> SearchedLocations { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnViewResultViewNotFoundEventData ViewResultViewNotFound { get; set; }
|
||||||
|
|
||||||
|
[NotificationName("Microsoft.AspNet.Mvc.ViewResultViewNotFound")]
|
||||||
|
public virtual void OnViewResultViewNotFound(
|
||||||
|
IProxyActionContext actionContext,
|
||||||
|
IProxyActionResult result,
|
||||||
|
string viewName,
|
||||||
|
IEnumerable<string> searchedLocations)
|
||||||
|
{
|
||||||
|
ViewResultViewNotFound = new OnViewResultViewNotFoundEventData()
|
||||||
|
{
|
||||||
|
ActionContext = actionContext,
|
||||||
|
Result = result,
|
||||||
|
ViewName = viewName,
|
||||||
|
SearchedLocations = searchedLocations,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,11 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.Http.Internal;
|
using Microsoft.AspNet.Http.Internal;
|
||||||
using Microsoft.AspNet.Mvc.Rendering;
|
using Microsoft.AspNet.Mvc.Rendering;
|
||||||
|
using Microsoft.AspNet.Mvc.TestCommon.Notification;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.Notification;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -203,6 +206,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
.Verifiable();
|
.Verifiable();
|
||||||
|
|
||||||
var serviceProvider = new Mock<IServiceProvider>();
|
var serviceProvider = new Mock<IServiceProvider>();
|
||||||
|
serviceProvider.Setup(s => s.GetService(typeof(INotifier)))
|
||||||
|
.Returns(new Notifier(new ProxyNotifierMethodAdapter()));
|
||||||
serviceProvider.Setup(p => p.GetService(typeof(ICompositeViewEngine)))
|
serviceProvider.Setup(p => p.GetService(typeof(ICompositeViewEngine)))
|
||||||
.Returns(viewEngine.Object);
|
.Returns(viewEngine.Object);
|
||||||
serviceProvider.Setup(p => p.GetService(typeof(ILogger<ViewResult>)))
|
serviceProvider.Setup(p => p.GetService(typeof(ILogger<ViewResult>)))
|
||||||
|
|
@ -228,6 +233,75 @@ namespace Microsoft.AspNet.Mvc
|
||||||
viewEngine.Verify();
|
viewEngine.Verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ViewResult_NotifiesViewFound()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var viewName = "myview";
|
||||||
|
var httpContext = GetHttpContext();
|
||||||
|
var context = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||||
|
|
||||||
|
var listener = new TestNotificationListener();
|
||||||
|
httpContext.RequestServices.GetRequiredService<INotifier>().EnlistTarget(listener);
|
||||||
|
|
||||||
|
var viewEngine = new Mock<IViewEngine>();
|
||||||
|
var view = Mock.Of<IView>();
|
||||||
|
|
||||||
|
viewEngine.Setup(e => e.FindView(context, "myview"))
|
||||||
|
.Returns(ViewEngineResult.Found("myview", view));
|
||||||
|
|
||||||
|
var viewResult = new ViewResult
|
||||||
|
{
|
||||||
|
ViewName = viewName,
|
||||||
|
ViewEngine = viewEngine.Object,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await viewResult.ExecuteResultAsync(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(listener.ViewResultViewFound);
|
||||||
|
Assert.NotNull(listener.ViewResultViewFound.ActionContext);
|
||||||
|
Assert.NotNull(listener.ViewResultViewFound.Result);
|
||||||
|
Assert.NotNull(listener.ViewResultViewFound.View);
|
||||||
|
Assert.Equal("myview", listener.ViewResultViewFound.ViewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ViewResult_NotifiesViewNotFound()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var viewName = "myview";
|
||||||
|
var httpContext = GetHttpContext();
|
||||||
|
var context = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
|
||||||
|
|
||||||
|
var listener = new TestNotificationListener();
|
||||||
|
httpContext.RequestServices.GetRequiredService<INotifier>().EnlistTarget(listener);
|
||||||
|
|
||||||
|
var viewEngine = new Mock<IViewEngine>();
|
||||||
|
var view = Mock.Of<IView>();
|
||||||
|
|
||||||
|
viewEngine.Setup(e => e.FindView(context, "myview"))
|
||||||
|
.Returns(ViewEngineResult.NotFound("myview", new string[] { "location/myview" }));
|
||||||
|
|
||||||
|
var viewResult = new ViewResult
|
||||||
|
{
|
||||||
|
ViewName = viewName,
|
||||||
|
ViewEngine = viewEngine.Object,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(
|
||||||
|
async () => await viewResult.ExecuteResultAsync(context));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(listener.ViewResultViewNotFound);
|
||||||
|
Assert.NotNull(listener.ViewResultViewNotFound.ActionContext);
|
||||||
|
Assert.NotNull(listener.ViewResultViewNotFound.Result);
|
||||||
|
Assert.Equal(new string[] { "location/myview" }, listener.ViewResultViewNotFound.SearchedLocations);
|
||||||
|
Assert.Equal("myview", listener.ViewResultViewNotFound.ViewName);
|
||||||
|
}
|
||||||
|
|
||||||
private HttpContext GetHttpContext()
|
private HttpContext GetHttpContext()
|
||||||
{
|
{
|
||||||
var serviceProvider = new Mock<IServiceProvider>();
|
var serviceProvider = new Mock<IServiceProvider>();
|
||||||
|
|
@ -241,6 +315,9 @@ namespace Microsoft.AspNet.Mvc
|
||||||
serviceProvider.Setup(s => s.GetService(typeof(IOptions<MvcViewOptions>)))
|
serviceProvider.Setup(s => s.GetService(typeof(IOptions<MvcViewOptions>)))
|
||||||
.Returns(optionsAccessor.Object);
|
.Returns(optionsAccessor.Object);
|
||||||
|
|
||||||
|
serviceProvider.Setup(s => s.GetService(typeof(INotifier)))
|
||||||
|
.Returns(new Notifier(new ProxyNotifierMethodAdapter()));
|
||||||
|
|
||||||
var httpContext = new DefaultHttpContext();
|
var httpContext = new DefaultHttpContext();
|
||||||
httpContext.RequestServices = serviceProvider.Object;
|
httpContext.RequestServices = serviceProvider.Object;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue