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.Framework.Internal;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.Notification;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
{
|
||||
|
|
@ -32,6 +33,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
||||
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
|
||||
[NotNull] ILogger logger,
|
||||
[NotNull] INotifier notifier,
|
||||
int maxModelValidationErrors)
|
||||
: base(
|
||||
actionContext,
|
||||
|
|
@ -43,6 +45,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
valueProviderFactories,
|
||||
actionBindingContextAccessor,
|
||||
logger,
|
||||
notifier,
|
||||
maxModelValidationErrors)
|
||||
{
|
||||
_descriptor = descriptor;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.Notification;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
|
|
@ -24,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
|
||||
private readonly int _maxModelValidationErrors;
|
||||
private readonly ILogger _logger;
|
||||
private readonly INotifier _notifier;
|
||||
|
||||
public ControllerActionInvokerProvider(
|
||||
IControllerFactory controllerFactory,
|
||||
|
|
@ -31,7 +33,8 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
IControllerActionArgumentBinder argumentBinder,
|
||||
IOptions<MvcOptions> optionsAccessor,
|
||||
IActionBindingContextAccessor actionBindingContextAccessor,
|
||||
ILoggerFactory loggerFactory)
|
||||
ILoggerFactory loggerFactory,
|
||||
INotifier notifier)
|
||||
{
|
||||
_controllerFactory = controllerFactory;
|
||||
_filterProviders = filterProviders.OrderBy(item => item.Order).ToArray();
|
||||
|
|
@ -43,8 +46,8 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
_valueProviderFactories = optionsAccessor.Options.ValueProviderFactories.ToArray();
|
||||
_actionBindingContextAccessor = actionBindingContextAccessor;
|
||||
_maxModelValidationErrors = optionsAccessor.Options.MaxModelValidationErrors;
|
||||
|
||||
_logger = loggerFactory.CreateLogger<ControllerActionInvoker>();
|
||||
_notifier = notifier;
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
|
@ -72,6 +75,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
_valueProviderFactories,
|
||||
_actionBindingContextAccessor,
|
||||
_logger,
|
||||
_notifier,
|
||||
_maxModelValidationErrors);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNet.Mvc.ModelBinding;
|
|||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.Notification;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core
|
||||
{
|
||||
|
|
@ -24,6 +25,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
|
||||
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
|
||||
private readonly ILogger _logger;
|
||||
private readonly INotifier _notifier;
|
||||
private readonly int _maxModelValidationErrors;
|
||||
|
||||
private IFilterMetadata[] _filters;
|
||||
|
|
@ -63,6 +65,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
||||
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
|
||||
[NotNull] ILogger logger,
|
||||
[NotNull] INotifier notifier,
|
||||
int maxModelValidationErrors)
|
||||
{
|
||||
ActionContext = actionContext;
|
||||
|
|
@ -75,6 +78,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
_valueProviderFactories = valueProviderFactories;
|
||||
_actionBindingContextAccessor = actionBindingContextAccessor;
|
||||
_logger = logger;
|
||||
_notifier = notifier;
|
||||
_maxModelValidationErrors = maxModelValidationErrors;
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +131,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Debug.Assert(_authorizationContext != null);
|
||||
if (_authorizationContext.Result != null)
|
||||
{
|
||||
await _authorizationContext.Result.ExecuteResultAsync(ActionContext);
|
||||
await InvokeResultAsync(_authorizationContext.Result);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -281,7 +285,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
ResourceFilterShortCircuitLogMessage,
|
||||
item.FilterAsync.GetType().FullName);
|
||||
|
||||
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
|
||||
await InvokeResultAsync(_resourceExecutingContext.Result);
|
||||
}
|
||||
|
||||
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
|
||||
|
|
@ -301,7 +305,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
|
||||
_logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.Filter.GetType().FullName);
|
||||
|
||||
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
|
||||
await InvokeResultAsync(_resourceExecutingContext.Result);
|
||||
|
||||
_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.
|
||||
// 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)
|
||||
{
|
||||
|
|
@ -558,12 +562,35 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
else
|
||||
{
|
||||
// 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(
|
||||
_actionExecutingContext,
|
||||
_filters,
|
||||
Instance)
|
||||
{
|
||||
Result = await InvokeActionAsync(_actionExecutingContext),
|
||||
Result = result
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -683,7 +710,15 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
}
|
||||
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);
|
||||
_resultExecutedContext = new ResultExecutedContext(
|
||||
|
|
@ -708,17 +743,28 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
return _resultExecutedContext;
|
||||
}
|
||||
|
||||
private async Task InvokeResultAsync()
|
||||
private async Task InvokeResultAsync(IActionResult result)
|
||||
{
|
||||
_cursor.SetStage(FilterStage.ActionResult);
|
||||
|
||||
// The empty result is always flowed back as the 'executed' result
|
||||
if (_resultExecutingContext.Result == null)
|
||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeActionResult"))
|
||||
{
|
||||
_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
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
context.RouteData = newRouteData;
|
||||
|
||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.ActionSelected"))
|
||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeAction"))
|
||||
{
|
||||
_notifier.Notify(
|
||||
"Microsoft.AspNet.Mvc.ActionSelected",
|
||||
"Microsoft.AspNet.Mvc.BeforeAction",
|
||||
new { actionDescriptor, httpContext = context.HttpContext, routeData = context.RouteData});
|
||||
}
|
||||
|
||||
|
|
@ -84,16 +84,16 @@ namespace Microsoft.AspNet.Mvc
|
|||
await InvokeActionAsync(context, actionDescriptor);
|
||||
context.IsHandled = true;
|
||||
}
|
||||
|
||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.ActionInvoked"))
|
||||
{
|
||||
_notifier.Notify(
|
||||
"Microsoft.AspNet.Mvc.ActionInvoked",
|
||||
new { actionDescriptor, httpContext = context.HttpContext });
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterAction"))
|
||||
{
|
||||
_notifier.Notify(
|
||||
"Microsoft.AspNet.Mvc.AfterAction",
|
||||
new { actionDescriptor, httpContext = context.HttpContext });
|
||||
}
|
||||
|
||||
if (!context.IsHandled)
|
||||
{
|
||||
context.RouteData = oldRouteData;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using Microsoft.Framework.Internal;
|
|||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.Notification;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
@ -55,17 +56,31 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <inheritdoc />
|
||||
public override async Task ExecuteResultAsync([NotNull] ActionContext context)
|
||||
{
|
||||
var viewEngine = ViewEngine ??
|
||||
context.HttpContext.RequestServices.GetRequiredService<ICompositeViewEngine>();
|
||||
var services = context.HttpContext.RequestServices;
|
||||
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 viewEngineResult = viewEngine.FindView(context, viewName);
|
||||
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(
|
||||
"The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}",
|
||||
viewName,
|
||||
|
|
@ -73,6 +88,12 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ using Microsoft.AspNet.Testing;
|
|||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.Logging.Testing;
|
||||
using Microsoft.Framework.Notification;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Moq;
|
||||
|
|
@ -2042,6 +2043,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
new IValueProviderFactory[0],
|
||||
new ActionBindingContextAccessor(),
|
||||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||
new Notifier(new ProxyNotifierMethodAdapter()),
|
||||
maxAllowedErrorsInModelState);
|
||||
|
||||
return invoker;
|
||||
|
|
@ -2104,6 +2106,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
new IValueProviderFactory[0],
|
||||
new ActionBindingContextAccessor(),
|
||||
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
|
||||
new Notifier(new ProxyNotifierMethodAdapter()),
|
||||
200);
|
||||
|
||||
// Act
|
||||
|
|
@ -2204,6 +2207,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
IReadOnlyList<IValueProviderFactory> valueProviderFactories,
|
||||
IActionBindingContextAccessor actionBindingContext,
|
||||
ILogger logger,
|
||||
INotifier notifier,
|
||||
int maxAllowedErrorsInModelState)
|
||||
: base(
|
||||
actionContext,
|
||||
|
|
@ -2218,6 +2222,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
valueProviderFactories,
|
||||
actionBindingContext,
|
||||
logger,
|
||||
notifier,
|
||||
maxAllowedErrorsInModelState)
|
||||
{
|
||||
ControllerFactory = controllerFactory;
|
||||
|
|
|
|||
|
|
@ -169,10 +169,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
await handler.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(listener?.ActionSelected.ActionDescriptor);
|
||||
Assert.NotNull(listener?.ActionSelected.HttpContext);
|
||||
Assert.NotNull(listener.BeforeAction?.ActionDescriptor);
|
||||
Assert.NotNull(listener.BeforeAction?.HttpContext);
|
||||
|
||||
var routeValues = listener?.ActionSelected?.RouteData?.Values;
|
||||
var routeValues = listener.BeforeAction?.RouteData?.Values;
|
||||
Assert.NotNull(routeValues);
|
||||
|
||||
Assert.Equal(1, routeValues.Count);
|
||||
|
|
@ -193,8 +193,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
await handler.RouteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(listener?.ActionInvoked.ActionDescriptor);
|
||||
Assert.NotNull(listener?.ActionInvoked.HttpContext);
|
||||
Assert.NotNull(listener.AfterAction?.ActionDescriptor);
|
||||
Assert.NotNull(listener.AfterAction?.HttpContext);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
public interface IActionDescriptor
|
||||
public interface IProxyHttpContext
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ using System.Collections.Generic;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||
{
|
||||
public interface IRouteData
|
||||
public interface IProxyRouteData
|
||||
{
|
||||
IReadOnlyList<object> Routers { get; }
|
||||
IDictionary<string, object> DataTokens { get; }
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||
{
|
||||
public interface IHttpContext
|
||||
public interface IProxyView
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,29 @@
|
|||
// 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Framework.Notification;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
||||
{
|
||||
public class TestNotificationListener
|
||||
{
|
||||
public OnActionSelectedEventData ActionSelected { get; set; }
|
||||
|
||||
[NotificationName("Microsoft.AspNet.Mvc.ActionSelected")]
|
||||
public virtual void OnActionSelected(
|
||||
IHttpContext httpContext,
|
||||
IRouteData routeData,
|
||||
IActionDescriptor actionDescriptor)
|
||||
public class OnBeforeActionEventData
|
||||
{
|
||||
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,
|
||||
HttpContext = httpContext,
|
||||
|
|
@ -23,31 +31,76 @@ namespace Microsoft.AspNet.Mvc.TestCommon.Notification
|
|||
};
|
||||
}
|
||||
|
||||
public OnActionInvokedEventData ActionInvoked { get; set; }
|
||||
|
||||
[NotificationName("Microsoft.AspNet.Mvc.ActionInvoked")]
|
||||
public virtual void OnActionInvoked(
|
||||
IHttpContext httpContext,
|
||||
IActionDescriptor actionDescriptor)
|
||||
public class OnAfterActionEventData
|
||||
{
|
||||
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,
|
||||
HttpContext = httpContext,
|
||||
};
|
||||
}
|
||||
|
||||
public class OnActionSelectedEventData
|
||||
public class OnViewResultViewFoundEventData
|
||||
{
|
||||
public IActionDescriptor ActionDescriptor { get; set; }
|
||||
public IHttpContext HttpContext { get; set; }
|
||||
public IRouteData RouteData { get; set; }
|
||||
public IProxyActionContext ActionContext { get; set; }
|
||||
public IProxyActionResult Result { 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; }
|
||||
public IHttpContext HttpContext { get; set; }
|
||||
ViewResultViewFound = new OnViewResultViewFoundEventData()
|
||||
{
|
||||
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.Internal;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using Microsoft.AspNet.Mvc.TestCommon.Notification;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.Notification;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Moq;
|
||||
|
|
@ -203,6 +206,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
.Verifiable();
|
||||
|
||||
var serviceProvider = new Mock<IServiceProvider>();
|
||||
serviceProvider.Setup(s => s.GetService(typeof(INotifier)))
|
||||
.Returns(new Notifier(new ProxyNotifierMethodAdapter()));
|
||||
serviceProvider.Setup(p => p.GetService(typeof(ICompositeViewEngine)))
|
||||
.Returns(viewEngine.Object);
|
||||
serviceProvider.Setup(p => p.GetService(typeof(ILogger<ViewResult>)))
|
||||
|
|
@ -228,6 +233,75 @@ namespace Microsoft.AspNet.Mvc
|
|||
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()
|
||||
{
|
||||
var serviceProvider = new Mock<IServiceProvider>();
|
||||
|
|
@ -241,6 +315,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
serviceProvider.Setup(s => s.GetService(typeof(IOptions<MvcViewOptions>)))
|
||||
.Returns(optionsAccessor.Object);
|
||||
|
||||
serviceProvider.Setup(s => s.GetService(typeof(INotifier)))
|
||||
.Returns(new Notifier(new ProxyNotifierMethodAdapter()));
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.RequestServices = serviceProvider.Object;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue