В отличие от большинства фильтров в ASP.NET Core, которые имеют обработчик событий "перед" и "после", фильтры исключений располагают только одним обработчиком:
OnException
(или
OnExceptionAsync
). Обработчик принимает один параметр,
ExceptionContext
, который предоставляет доступ к
ActionContext
, а также к сгенерированному исключению.
Кроме того, фильтры принимают участие во внедрении зависимостей, позволяя получить доступ в коде к любому элементу внутри контейнера. В рассматриваемом
примере вам необходим экземпляр реализации
IWebHostEnvironment
, внедренный в фильтр, который будет использоваться для выяснения среды времени выполнения. Если средой является
Development
, тогда ответ должен также включать трассировку стека. Добавьте переменную уровня класса для хранения экземпляра реализации
public CustomExceptionFilterAttribute(IWebHostEnvironment hostEnvironment)
{
_hostEnvironment = hostEnvironment;
}
Код в обработчике
OnException
проверяет тип сгенерированного исключения и строит соответствующий ответ. В случае среды
Development
в сообщение ответа включается трассировка стека. Затем создается динамический объект, который содержит значения для отправки вызывающему запросу, и возвращается в
IActionResult
. Вот модифицированный код метода:
public override void OnException(ExceptionContext context)
new {Error = error, Message = message, StackTrace = stackTrace});
break;
default:
error = "General Error.";
actionResult = new ObjectResult(
new {Error = error, Message = message, StackTrace = stackTrace})
{
StatusCode = 500
};
break;
}
//context.ExceptionHandled = true; // Если убрать здесь комментарий,
// то исключение поглощается
context.Result = actionResult;
}
Если вы хотите, чтобы фильтр исключений поглотил исключение и установил код состояния в 200 (скажем, для регистрации ошибки в журнале,
не возвращая ее клиенту), тогда поместите следующую строку перед установкой
Result
(в предыдущем примере кода просто уберите комментарий):
context.ExceptionHandled = true;
Добавление фильтров в конвейер обработки
Фильтры можно применять к методам действий, контроллерам или глобально к приложению. Код "перед" фильтров выполняется снаружи вовнутрь (глобальный, контроллер, метод действия), в то время как код "после" фильтров выполняется изнутри наружу (метод действия, контроллер, глобальный).
Чтобы протестировать фильтр исключений, откройте файл
WeatherForecastController.cs
и обновите метод действия
Get
показанным ниже кодом:
[HttpGet]
public IEnumerable<WeatherForecast> Get
{
_logger.LogAppWarning("This is a test");
throw new Exception("Test Exception");
...
}
Запустите приложение и испытайте метод с использованием Swagger. Результаты, отображенные в пользовательском интерфейсе Swagger должны соответствовать следующему выводу (трассировка стека приведена с сокращениями):
{
"Error": "General Error.",
"Message": "Test Exception",
"StackTrace": " at AutoLot.Api.Controllers.WeatherForecastController.Get in