Add ExceptionHandled to ExceptionContext (#4825)

This commit is contained in:
Ryan Brandenburg 2016-06-09 15:22:11 -07:00 committed by GitHub
parent 8c8fd6446b
commit 5339a3e0ce
4 changed files with 69 additions and 11 deletions

View File

@ -68,6 +68,11 @@ namespace Microsoft.AspNetCore.Mvc.Filters
}
}
/// <summary>
/// Gets or sets an indication that the <see cref="Exception"/> has been handled.
/// </summary>
public virtual bool ExceptionHandled { get; set; } = false;
/// <summary>
/// Gets or sets the <see cref="IActionResult"/>.
/// </summary>

View File

@ -14,7 +14,6 @@ using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Mvc.Internal
@ -354,7 +353,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
Result = _exceptionContext.Result,
};
}
else if (_exceptionContext.Exception != null)
else if (_exceptionContext.Exception != null && !_exceptionContext.ExceptionHandled)
{
// If we get here, this means that we have an unhandled exception.
// Exception filted didn't handle this, so send it on to resource filters.
@ -412,7 +411,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
await InvokeExceptionFilterAsync();
Debug.Assert(_exceptionContext != null);
if (_exceptionContext.Exception != null)
if (_exceptionContext.Exception != null && !_exceptionContext.ExceptionHandled)
{
_diagnosticSource.BeforeOnExceptionAsync(_exceptionContext, current.FilterAsync);
@ -422,7 +421,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
_diagnosticSource.AfterOnExceptionAsync(_exceptionContext, current.FilterAsync);
if (_exceptionContext.Exception == null)
if (_exceptionContext.Exception == null || _exceptionContext.ExceptionHandled)
{
_logger.ExceptionFilterShortCircuited(current.FilterAsync);
}
@ -435,7 +434,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
await InvokeExceptionFilterAsync();
Debug.Assert(_exceptionContext != null);
if (_exceptionContext.Exception != null)
if (_exceptionContext.Exception != null && !_exceptionContext.ExceptionHandled)
{
_diagnosticSource.BeforeOnException(_exceptionContext, current.Filter);
@ -445,7 +444,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
_diagnosticSource.AfterOnException(_exceptionContext, current.Filter);
if (_exceptionContext.Exception == null)
if (_exceptionContext.Exception == null || _exceptionContext.ExceptionHandled)
{
_logger.ExceptionFilterShortCircuited(current.Filter);
}

View File

@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}
[Fact]
public async Task InvokeAction_InvokesExceptionFilter_ShortCircuit()
public async Task InvokeAction_InvokesExceptionFilter_ShortCircuit_ExceptionNull()
{
// Arrange
var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict);
@ -171,7 +171,62 @@ namespace Microsoft.AspNetCore.Mvc.Internal
}
[Fact]
public async Task InvokeAction_InvokesAsyncExceptionFilter_ShortCircuit()
public async Task InvokeAction_InvokesExceptionFilter_ShortCircuit_ExceptionHandled()
{
// Arrange
var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict);
var filter2 = new Mock<IExceptionFilter>(MockBehavior.Strict);
filter2
.Setup(f => f.OnException(It.IsAny<ExceptionContext>()))
.Callback<ExceptionContext>(context =>
{
context.ExceptionHandled = true;
})
.Verifiable();
var invoker = CreateInvoker(new[] { filter1.Object, filter2.Object }, actionThrows: true);
// Act
await invoker.InvokeAsync();
// Assert
filter2.Verify(
f => f.OnException(It.IsAny<ExceptionContext>()),
Times.Once());
}
[Fact]
public async Task InvokeAction_InvokesAsyncExceptionFilter_ShortCircuit_ExceptionNull()
{
// Arrange
var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict);
var filter2 = new Mock<IAsyncExceptionFilter>(MockBehavior.Strict);
filter2
.Setup(f => f.OnExceptionAsync(It.IsAny<ExceptionContext>()))
.Callback<ExceptionContext>(context =>
{
filter2.ToString();
context.Exception = null;
})
.Returns<ExceptionContext>((context) => Task.FromResult(true))
.Verifiable();
var filterMetadata = new IFilterMetadata[] { filter1.Object, filter2.Object };
var invoker = CreateInvoker(filterMetadata, actionThrows: true);
// Act
await invoker.InvokeAsync();
// Assert
filter2.Verify(
f => f.OnExceptionAsync(It.IsAny<ExceptionContext>()),
Times.Once());
}
[Fact]
public async Task InvokeAction_InvokesAsyncExceptionFilter_ShortCircuit_ExceptionHandled()
{
// Arrange
var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict);
@ -181,8 +236,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
.Setup(f => f.OnExceptionAsync(It.IsAny<ExceptionContext>()))
.Callback<ExceptionContext>(context =>
{
filter2.ToString();
context.Exception = null;
context.ExceptionHandled = true;
})
.Returns<ExceptionContext>((context) => Task.FromResult(true))
.Verifiable();

View File

@ -9,7 +9,7 @@ namespace FiltersWebSite
{
public override void OnException(ExceptionContext context)
{
context.Exception = null;
context.ExceptionHandled = true;
}
}
}