Implement manual state machine

This commit is contained in:
Ryan Nowak 2016-05-17 13:28:37 -07:00
parent d60ed06c19
commit e77dc3af6a
4 changed files with 1335 additions and 583 deletions

View File

@ -2,10 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace MvcSandbox
{
@ -15,6 +17,10 @@ namespace MvcSandbox
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Insert(0, ServiceDescriptor.Singleton(
typeof(IConfigureOptions<AntiforgeryOptions>),
new ConfigureOptions<AntiforgeryOptions>(options => options.CookieName = "<choose a name>")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
_contentResultExecuting(logger, contentType, null);
}
public static void ActionMethodExecuting(this ILogger logger, ActionExecutingContext context, object[] arguments)
public static void ActionMethodExecuting(this ILogger logger, ControllerContext context, object[] arguments)
{
if (logger.IsEnabled(LogLevel.Information))
{
@ -269,7 +269,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}
}
public static void ActionMethodExecuted(this ILogger logger, ActionExecutingContext context, IActionResult result)
public static void ActionMethodExecuted(this ILogger logger, ControllerContext context, IActionResult result)
{
if (logger.IsEnabled(LogLevel.Debug))
{

View File

@ -1802,6 +1802,56 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Assert.False(invoker.ControllerFactory.CreateCalled);
}
[Fact]
public async Task InvokeAction_InvokesAsyncResourceFilter_ShortCircuit_WithoutResult()
{
// Arrange
ResourceExecutedContext context = null;
var resourceFilter1 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
resourceFilter1
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
{
context = await next();
})
.Verifiable();
var resourceFilter2 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
resourceFilter2
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>((c, next) =>
{
return Task.FromResult(true);
})
.Verifiable();
var resourceFilter3 = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
var exceptionFilter = new Mock<IExceptionFilter>(MockBehavior.Strict);
var actionFilter = new Mock<IAsyncActionFilter>(MockBehavior.Strict);
var resultFilter = new Mock<IAsyncResultFilter>(MockBehavior.Strict);
var invoker = CreateInvoker(
new IFilterMetadata[]
{
resourceFilter1.Object, // This filter should see the result retured from resourceFilter2
resourceFilter2.Object, // This filter will short circuit
resourceFilter3.Object, // This shouldn't run - it will throw if it does
exceptionFilter.Object, // This shouldn't run - it will throw if it does
actionFilter.Object, // This shouldn't run - it will throw if it does
resultFilter.Object // This shouldn't run - it will throw if it does
},
// The action won't run
actionThrows: true);
// Act
await invoker.InvokeAsync();
// Assert
Assert.Null(context.Result);
Assert.True(context.Canceled);
Assert.False(invoker.ControllerFactory.CreateCalled);
}
[Fact]
public async Task InvokeAction_InvokesResourceFilter_ShortCircuit()
{
@ -2701,6 +2751,49 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Assert.NotNull(listener.AfterAction?.ActionDescriptor);
Assert.NotNull(listener.AfterAction?.HttpContext);
}
public async Task InvokeAction_ExceptionBubbling_AsyncActionFilter_To_ResourceFilter()
{
// Arrange
var resourceFilter = new Mock<IAsyncResourceFilter>(MockBehavior.Strict);
resourceFilter
.Setup(f => f.OnResourceExecutionAsync(It.IsAny<ResourceExecutingContext>(), It.IsAny<ResourceExecutionDelegate>()))
.Returns<ResourceExecutingContext, ResourceExecutionDelegate>(async (c, next) =>
{
var context = await next();
Assert.Same(_actionException, context.Exception);
context.ExceptionHandled = true;
});
var actionFilter1 = new Mock<IAsyncActionFilter>(MockBehavior.Strict);
actionFilter1
.Setup(f => f.OnActionExecutionAsync(It.IsAny<ActionExecutingContext>(), It.IsAny<ActionExecutionDelegate>()))
.Returns<ActionExecutingContext, ActionExecutionDelegate>(async (c, next) =>
{
await next();
});
var actionFilter2 = new Mock<IAsyncActionFilter>(MockBehavior.Strict);
actionFilter2
.Setup(f => f.OnActionExecutionAsync(It.IsAny<ActionExecutingContext>(), It.IsAny<ActionExecutionDelegate>()))
.Returns<ActionExecutingContext, ActionExecutionDelegate>(async (c, next) =>
{
await next();
});
var invoker = CreateInvoker(
new IFilterMetadata[]
{
resourceFilter.Object,
actionFilter1.Object,
actionFilter2.Object,
},
// The action won't run
actionThrows: true);
// Act & Assert
await invoker.InvokeAsync();
}
private TestControllerActionInvoker CreateInvoker(
IFilterMetadata filter,