Implement manual state machine
This commit is contained in:
parent
d60ed06c19
commit
e77dc3af6a
|
|
@ -2,10 +2,12 @@
|
||||||
// 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.IO;
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Antiforgery;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace MvcSandbox
|
namespace MvcSandbox
|
||||||
{
|
{
|
||||||
|
|
@ -15,6 +17,10 @@ namespace MvcSandbox
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddMvc();
|
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.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
_contentResultExecuting(logger, contentType, null);
|
_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))
|
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))
|
if (logger.IsEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1802,6 +1802,56 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
Assert.False(invoker.ControllerFactory.CreateCalled);
|
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]
|
[Fact]
|
||||||
public async Task InvokeAction_InvokesResourceFilter_ShortCircuit()
|
public async Task InvokeAction_InvokesResourceFilter_ShortCircuit()
|
||||||
{
|
{
|
||||||
|
|
@ -2701,6 +2751,49 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
Assert.NotNull(listener.AfterAction?.ActionDescriptor);
|
Assert.NotNull(listener.AfterAction?.ActionDescriptor);
|
||||||
Assert.NotNull(listener.AfterAction?.HttpContext);
|
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(
|
private TestControllerActionInvoker CreateInvoker(
|
||||||
IFilterMetadata filter,
|
IFilterMetadata filter,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue