Add ExceptionHandled to ExceptionContext (#4825)
This commit is contained in:
parent
8c8fd6446b
commit
5339a3e0ce
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace FiltersWebSite
|
|||
{
|
||||
public override void OnException(ExceptionContext context)
|
||||
{
|
||||
context.Exception = null;
|
||||
context.ExceptionHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue