Чтобы сообщить конвейеру ASP.NET Core MVC о том, что вы обработали исключение, вам нужно установить ActionExecutedContext.ExceptionHandled
в true
. Поскольку в показанном вами коде этого нет, конвейер ASP.NET Core MVC использует собственную логику обработки ошибок, чтобы преобразовать необработанное исключение (которое он считает) в ответ 500.
Теперь - это свойство существует в ActionExecutedContext
, а не в ActionExecutingContext
(которое вы используете в своем коде). Это имеет смысл, поскольку ActionExecutingContext
представляет состояние до выполнения действия, а ActionExecutedContext
представляет состояние после выполнения действия. Это означает, что вам понадобится следующий набор изменений:
- Обновите вашу функцию
OnExceptionAsync
, чтобы она заняла ActionExecutedContext
вместо ActionExecutingContext
.
- Обновите вызов до
OnExceptionAsync
, указав executed
вместо context
. Пока вы здесь, вы также можете свернуть параметры метода до просто executed
(я покажу это в коде ниже).
- Установите
context.ExceptionHandled
на true
, как только вы обработаете исключение. :)
Я взял код из вашего вопроса, вычеркнул часть кода, который не имеет отношения к проблеме, и применил эти изменения, которые я назвал соответствующими номерами сверху:
public abstract class GenericActionFilter : ActionFilterAttribute
{
public override async Task OnActionExecutionAsync(ActionExecutingContext context,
ActionExecutionDelegate next)
{
if (await OnBeforeActionExecutionAsync(context))
{
var executed = await next();
if (executed.Exception != null && !executed.ExceptionHandled)
{
await OnExceptionAsync(executed); // #2.
}
else
{
// NOTE: You might want to use executed here too.
await OnAfterActionExecutionAsync(context);
}
}
}
// ...
public virtual Task OnExceptionAsync(ActionExecutedContext context) // #1.
{
return Task.CompletedTask;
}
}
public class ExceptionFilter : GenericActionFilter
{
public override Task OnExceptionAsync(ActionExecutedContext context) // #1, #2.
{
Logger.Error(context.Exception); // #2 (single parameter).
context.Result = new ContentResult { ... };
context.ExceptionHandled = true; // #3.
return Task.CompletedTask;
}
}