Skip to content

Commit e384938

Browse files
committed
Add more event notification data points
Also includes some cleanup of the testing code that we're using with proxies.
1 parent 07fabde commit e384938

File tree

15 files changed

+291
-55
lines changed

15 files changed

+291
-55
lines changed

src/Microsoft.AspNet.Mvc.Core/ControllerActionInvoker.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
1111
using Microsoft.Framework.Internal;
1212
using Microsoft.Framework.Logging;
13+
using Microsoft.Framework.Notification;
1314

1415
namespace Microsoft.AspNet.Mvc.Core
1516
{
@@ -32,6 +33,7 @@ public ControllerActionInvoker(
3233
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
3334
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
3435
[NotNull] ILogger logger,
36+
[NotNull] INotifier notifier,
3537
int maxModelValidationErrors)
3638
: base(
3739
actionContext,
@@ -43,6 +45,7 @@ public ControllerActionInvoker(
4345
valueProviderFactories,
4446
actionBindingContextAccessor,
4547
logger,
48+
notifier,
4649
maxModelValidationErrors)
4750
{
4851
_descriptor = descriptor;

src/Microsoft.AspNet.Mvc.Core/ControllerActionInvokerProvider.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
88
using Microsoft.Framework.Internal;
99
using Microsoft.Framework.Logging;
10+
using Microsoft.Framework.Notification;
1011
using Microsoft.Framework.OptionsModel;
1112

1213
namespace Microsoft.AspNet.Mvc.Core
@@ -24,14 +25,16 @@ public class ControllerActionInvokerProvider : IActionInvokerProvider
2425
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
2526
private readonly int _maxModelValidationErrors;
2627
private readonly ILogger _logger;
28+
private readonly INotifier _notifier;
2729

2830
public ControllerActionInvokerProvider(
2931
IControllerFactory controllerFactory,
3032
IEnumerable<IFilterProvider> filterProviders,
3133
IControllerActionArgumentBinder argumentBinder,
3234
IOptions<MvcOptions> optionsAccessor,
3335
IActionBindingContextAccessor actionBindingContextAccessor,
34-
ILoggerFactory loggerFactory)
36+
ILoggerFactory loggerFactory,
37+
INotifier notifier)
3538
{
3639
_controllerFactory = controllerFactory;
3740
_filterProviders = filterProviders.OrderBy(item => item.Order).ToArray();
@@ -43,8 +46,8 @@ public ControllerActionInvokerProvider(
4346
_valueProviderFactories = optionsAccessor.Options.ValueProviderFactories.ToArray();
4447
_actionBindingContextAccessor = actionBindingContextAccessor;
4548
_maxModelValidationErrors = optionsAccessor.Options.MaxModelValidationErrors;
46-
4749
_logger = loggerFactory.CreateLogger<ControllerActionInvoker>();
50+
_notifier = notifier;
4851
}
4952

5053
public int Order
@@ -72,6 +75,7 @@ public void OnProvidersExecuting([NotNull] ActionInvokerProviderContext context)
7275
_valueProviderFactories,
7376
_actionBindingContextAccessor,
7477
_logger,
78+
_notifier,
7579
_maxModelValidationErrors);
7680
}
7781
}

src/Microsoft.AspNet.Mvc.Core/FilterActionInvoker.cs

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
1212
using Microsoft.Framework.Internal;
1313
using Microsoft.Framework.Logging;
14+
using Microsoft.Framework.Notification;
1415

1516
namespace Microsoft.AspNet.Mvc.Core
1617
{
@@ -24,6 +25,7 @@ public abstract class FilterActionInvoker : IActionInvoker
2425
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
2526
private readonly IActionBindingContextAccessor _actionBindingContextAccessor;
2627
private readonly ILogger _logger;
28+
private readonly INotifier _notifier;
2729
private readonly int _maxModelValidationErrors;
2830

2931
private IFilterMetadata[] _filters;
@@ -63,6 +65,7 @@ public FilterActionInvoker(
6365
[NotNull] IReadOnlyList<IValueProviderFactory> valueProviderFactories,
6466
[NotNull] IActionBindingContextAccessor actionBindingContextAccessor,
6567
[NotNull] ILogger logger,
68+
[NotNull] INotifier notifier,
6669
int maxModelValidationErrors)
6770
{
6871
ActionContext = actionContext;
@@ -75,6 +78,7 @@ public FilterActionInvoker(
7578
_valueProviderFactories = valueProviderFactories;
7679
_actionBindingContextAccessor = actionBindingContextAccessor;
7780
_logger = logger;
81+
_notifier = notifier;
7882
_maxModelValidationErrors = maxModelValidationErrors;
7983
}
8084

@@ -127,7 +131,7 @@ public virtual async Task InvokeAsync()
127131
Debug.Assert(_authorizationContext != null);
128132
if (_authorizationContext.Result != null)
129133
{
130-
await _authorizationContext.Result.ExecuteResultAsync(ActionContext);
134+
await InvokeResultAsync(_authorizationContext.Result);
131135
return;
132136
}
133137

@@ -281,7 +285,7 @@ await item.FilterAsync.OnResourceExecutionAsync(
281285
ResourceFilterShortCircuitLogMessage,
282286
item.FilterAsync.GetType().FullName);
283287

284-
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
288+
await InvokeResultAsync(_resourceExecutingContext.Result);
285289
}
286290

287291
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
@@ -301,7 +305,7 @@ await item.FilterAsync.OnResourceExecutionAsync(
301305

302306
_logger.LogVerbose(ResourceFilterShortCircuitLogMessage, item.Filter.GetType().FullName);
303307

304-
await _resourceExecutingContext.Result.ExecuteResultAsync(ActionContext);
308+
await InvokeResultAsync(_resourceExecutingContext.Result);
305309

306310
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
307311
{
@@ -343,7 +347,7 @@ await item.FilterAsync.OnResourceExecutionAsync(
343347
{
344348
// This means that exception filters returned a result to 'handle' an error.
345349
// We're not interested in seeing the exception details since it was handled.
346-
await _exceptionContext.Result.ExecuteResultAsync(ActionContext);
350+
await InvokeResultAsync(_exceptionContext.Result);
347351

348352
_resourceExecutedContext = new ResourceExecutedContext(_resourceExecutingContext, _filters)
349353
{
@@ -558,12 +562,35 @@ private async Task<ActionExecutedContext> InvokeActionFilterAsync()
558562
else
559563
{
560564
// All action filters have run, execute the action method.
565+
IActionResult result = null;
566+
567+
try
568+
{
569+
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeActionMethod"))
570+
{
571+
_notifier.Notify(
572+
"Microsoft.AspNet.Mvc.BeforeActionMethod",
573+
new { actionContext = ActionContext, arguments = _actionExecutingContext.ActionArguments });
574+
}
575+
576+
result = await InvokeActionAsync(_actionExecutingContext);
577+
}
578+
finally
579+
{
580+
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterActionMethod"))
581+
{
582+
_notifier.Notify(
583+
"Microsoft.AspNet.Mvc.AfterActionMethod",
584+
new { actionContext = ActionContext, result });
585+
}
586+
}
587+
561588
_actionExecutedContext = new ActionExecutedContext(
562589
_actionExecutingContext,
563590
_filters,
564591
Instance)
565592
{
566-
Result = await InvokeActionAsync(_actionExecutingContext),
593+
Result = result
567594
};
568595
}
569596
}
@@ -683,7 +710,15 @@ private async Task<ResultExecutedContext> InvokeResultFilterAsync()
683710
}
684711
else
685712
{
686-
await InvokeResultAsync();
713+
_cursor.SetStage(FilterStage.ActionResult);
714+
715+
// The empty result is always flowed back as the 'executed' result
716+
if (_resultExecutingContext.Result == null)
717+
{
718+
_resultExecutingContext.Result = new EmptyResult();
719+
}
720+
721+
await InvokeResultAsync(_resultExecutingContext.Result);
687722

688723
Debug.Assert(_resultExecutedContext == null);
689724
_resultExecutedContext = new ResultExecutedContext(
@@ -708,17 +743,28 @@ private async Task<ResultExecutedContext> InvokeResultFilterAsync()
708743
return _resultExecutedContext;
709744
}
710745

711-
private async Task InvokeResultAsync()
746+
private async Task InvokeResultAsync(IActionResult result)
712747
{
713-
_cursor.SetStage(FilterStage.ActionResult);
714-
715-
// The empty result is always flowed back as the 'executed' result
716-
if (_resultExecutingContext.Result == null)
748+
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeActionResult"))
717749
{
718-
_resultExecutingContext.Result = new EmptyResult();
750+
_notifier.Notify(
751+
"Microsoft.AspNet.Mvc.BeforeActionResult",
752+
new { actionContext = ActionContext, result });
719753
}
720754

721-
await _resultExecutingContext.Result.ExecuteResultAsync(_resultExecutingContext);
755+
try
756+
{
757+
await result.ExecuteResultAsync(ActionContext);
758+
}
759+
finally
760+
{
761+
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterActionResult"))
762+
{
763+
_notifier.Notify(
764+
"Microsoft.AspNet.Mvc.AfterActionResult",
765+
new { actionContext = ActionContext, result });
766+
}
767+
}
722768
}
723769

724770
private enum FilterStage

src/Microsoft.AspNet.Mvc.Core/MvcRouteHandler.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ public async Task RouteAsync([NotNull] RouteContext context)
7070
{
7171
context.RouteData = newRouteData;
7272

73-
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.ActionSelected"))
73+
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.BeforeAction"))
7474
{
7575
_notifier.Notify(
76-
"Microsoft.AspNet.Mvc.ActionSelected",
76+
"Microsoft.AspNet.Mvc.BeforeAction",
7777
new { actionDescriptor, httpContext = context.HttpContext, routeData = context.RouteData});
7878
}
7979

@@ -84,16 +84,16 @@ public async Task RouteAsync([NotNull] RouteContext context)
8484
await InvokeActionAsync(context, actionDescriptor);
8585
context.IsHandled = true;
8686
}
87-
88-
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.ActionInvoked"))
87+
}
88+
finally
89+
{
90+
if (_notifier.ShouldNotify("Microsoft.AspNet.Mvc.AfterAction"))
8991
{
9092
_notifier.Notify(
91-
"Microsoft.AspNet.Mvc.ActionInvoked",
93+
"Microsoft.AspNet.Mvc.AfterAction",
9294
new { actionDescriptor, httpContext = context.HttpContext });
9395
}
94-
}
95-
finally
96-
{
96+
9797
if (!context.IsHandled)
9898
{
9999
context.RouteData = oldRouteData;

src/Microsoft.AspNet.Mvc.ViewFeatures/ViewResult.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.Framework.Logging;
1010
using Microsoft.Net.Http.Headers;
1111
using Microsoft.Framework.OptionsModel;
12+
using Microsoft.Framework.Notification;
1213

1314
namespace Microsoft.AspNet.Mvc
1415
{
@@ -55,24 +56,44 @@ public class ViewResult : ActionResult
5556
/// <inheritdoc />
5657
public override async Task ExecuteResultAsync([NotNull] ActionContext context)
5758
{
58-
var viewEngine = ViewEngine ??
59-
context.HttpContext.RequestServices.GetRequiredService<ICompositeViewEngine>();
59+
var services = context.HttpContext.RequestServices;
60+
var viewEngine = ViewEngine ?? services.GetRequiredService<ICompositeViewEngine>();
6061

61-
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<ViewResult>>();
62+
var logger = services.GetRequiredService<ILogger<ViewResult>>();
63+
var notifier = services.GetRequiredService<INotifier>();
6264

63-
var options = context.HttpContext.RequestServices.GetRequiredService<IOptions<MvcViewOptions>>();
65+
var options = services.GetRequiredService<IOptions<MvcViewOptions>>();
6466

6567
var viewName = ViewName ?? context.ActionDescriptor.Name;
6668
var viewEngineResult = viewEngine.FindView(context, viewName);
6769
if(!viewEngineResult.Success)
6870
{
71+
if (notifier.ShouldNotify("Microsoft.AspNet.Mvc.ViewResultViewNotFound"))
72+
{
73+
notifier.Notify(
74+
"Microsoft.AspNet.Mvc.ViewResultViewNotFound",
75+
new
76+
{
77+
actionContext = context,
78+
result = this,
79+
viewName = viewName,
80+
searchedLocations = viewEngineResult.SearchedLocations
81+
});
82+
}
83+
6984
logger.LogError(
7085
"The view '{ViewName}' was not found. Searched locations: {SearchedViewLocations}",
7186
viewName,
7287
viewEngineResult.SearchedLocations);
7388
}
7489

7590
var view = viewEngineResult.EnsureSuccessful().View;
91+
if (notifier.ShouldNotify("Microsoft.AspNet.Mvc.ViewResultViewFound"))
92+
{
93+
notifier.Notify(
94+
"Microsoft.AspNet.Mvc.ViewResultViewFound",
95+
new { actionContext = context, result = this, viewName, view = view });
96+
}
7697

7798
logger.LogVerbose("The view '{ViewName}' was found.", viewName);
7899

test/Microsoft.AspNet.Mvc.Core.Test/ControllerActionInvokerTest.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Microsoft.Framework.Internal;
1818
using Microsoft.Framework.Logging;
1919
using Microsoft.Framework.Logging.Testing;
20+
using Microsoft.Framework.Notification;
2021
using Microsoft.Framework.OptionsModel;
2122
using Microsoft.Net.Http.Headers;
2223
using Moq;
@@ -2042,6 +2043,7 @@ private TestControllerActionInvoker CreateInvoker(
20422043
new IValueProviderFactory[0],
20432044
new ActionBindingContextAccessor(),
20442045
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
2046+
new Notifier(new ProxyNotifierMethodAdapter()),
20452047
maxAllowedErrorsInModelState);
20462048

20472049
return invoker;
@@ -2104,6 +2106,7 @@ public async Task Invoke_UsesDefaultValuesIfNotBound()
21042106
new IValueProviderFactory[0],
21052107
new ActionBindingContextAccessor(),
21062108
new NullLoggerFactory().CreateLogger<ControllerActionInvoker>(),
2109+
new Notifier(new ProxyNotifierMethodAdapter()),
21072110
200);
21082111

21092112
// Act
@@ -2204,6 +2207,7 @@ public TestControllerActionInvoker(
22042207
IReadOnlyList<IValueProviderFactory> valueProviderFactories,
22052208
IActionBindingContextAccessor actionBindingContext,
22062209
ILogger logger,
2210+
INotifier notifier,
22072211
int maxAllowedErrorsInModelState)
22082212
: base(
22092213
actionContext,
@@ -2218,6 +2222,7 @@ public TestControllerActionInvoker(
22182222
valueProviderFactories,
22192223
actionBindingContext,
22202224
logger,
2225+
notifier,
22212226
maxAllowedErrorsInModelState)
22222227
{
22232228
ControllerFactory = controllerFactory;

test/Microsoft.AspNet.Mvc.Core.Test/MvcRouteHandlerTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,10 @@ public async Task RouteAsync_Notifies_ActionSelected()
169169
await handler.RouteAsync(context);
170170

171171
// Assert
172-
Assert.NotNull(listener?.ActionSelected.ActionDescriptor);
173-
Assert.NotNull(listener?.ActionSelected.HttpContext);
172+
Assert.NotNull(listener.BeforeAction?.ActionDescriptor);
173+
Assert.NotNull(listener.BeforeAction?.HttpContext);
174174

175-
var routeValues = listener?.ActionSelected?.RouteData?.Values;
175+
var routeValues = listener.BeforeAction?.RouteData?.Values;
176176
Assert.NotNull(routeValues);
177177

178178
Assert.Equal(1, routeValues.Count);
@@ -193,8 +193,8 @@ public async Task RouteAsync_Notifies_ActionInvoked()
193193
await handler.RouteAsync(context);
194194

195195
// Assert
196-
Assert.NotNull(listener?.ActionInvoked.ActionDescriptor);
197-
Assert.NotNull(listener?.ActionInvoked.HttpContext);
196+
Assert.NotNull(listener.AfterAction?.ActionDescriptor);
197+
Assert.NotNull(listener.AfterAction?.HttpContext);
198198
}
199199

200200
private RouteContext CreateRouteContext(
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
namespace Microsoft.AspNet.Mvc.TestCommon.Notification
5+
{
6+
public interface IProxyActionContext
7+
{
8+
}
9+
}

0 commit comments

Comments
 (0)