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> /// <summary>
/// Gets or sets the <see cref="IActionResult"/>. /// Gets or sets the <see cref="IActionResult"/>.
/// </summary> /// </summary>

View File

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

View File

@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
} }
[Fact] [Fact]
public async Task InvokeAction_InvokesExceptionFilter_ShortCircuit() public async Task InvokeAction_InvokesExceptionFilter_ShortCircuit_ExceptionNull()
{ {
// Arrange // Arrange
var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict); var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict);
@ -171,7 +171,62 @@ namespace Microsoft.AspNetCore.Mvc.Internal
} }
[Fact] [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 // Arrange
var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict); var filter1 = new Mock<IExceptionFilter>(MockBehavior.Strict);
@ -181,8 +236,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
.Setup(f => f.OnExceptionAsync(It.IsAny<ExceptionContext>())) .Setup(f => f.OnExceptionAsync(It.IsAny<ExceptionContext>()))
.Callback<ExceptionContext>(context => .Callback<ExceptionContext>(context =>
{ {
filter2.ToString(); context.ExceptionHandled = true;
context.Exception = null;
}) })
.Returns<ExceptionContext>((context) => Task.FromResult(true)) .Returns<ExceptionContext>((context) => Task.FromResult(true))
.Verifiable(); .Verifiable();

View File

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