Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Фильтры исключений позволяют обработать исключения, возникшие в методе во время выполнения запроса. Все фильтры исключений реализуют интерфейс
IExceptionFilter
из пространства имен System.Web.Http.Filters
:
public interface IExceptionFilter : IFilter { Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken); }
Метод ExecuteExceptionFilterAsync
вызывается при возникновении исключения в методе контроллера.
В качестве параметров в метод передается контекст HttpActionExecutedContext
с полной информацией о запросе, а также токен
отмены операции cancellationToken.
Создадим свой фильтр исключений:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web.Http.Filters; namespace WebApiApp.Filters { public class ArrayExceptionAttribute : Attribute, IExceptionFilter { public Task ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { if (actionExecutedContext.Exception != null && actionExecutedContext.Exception is IndexOutOfRangeException) { actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse( HttpStatusCode.BadRequest, "Элемент вне диапазона"); } return Task.FromResult<object>(null); } public bool AllowMultiple { get { return true; } } } }
С помощью свойства actionExecutedContext.Exception
мы можем получить информацию об исключении, возникшем в методе контроллера.
А используя метод actionExecutedContext.Request.CreateErrorResponse()
можно переопределить ответ, который генерирует метод контроллера. В итоге
пользователь получит сообщение, которое сгенерировал фильтр исключений.
Применим фильтр к методу:
[ArrayExceptionAttribute] public string Get(int id) { string[] letters = new string[] { "aab", "aba", "baa" }; return letters[id]; }
Если мы передадим в метод для параметра id значение больше 2, то пользователь увидит в браузере сообщение об ошибке от фильтра исключений:
Кроме прямой реализации интерфейса IExceptionFilter мы можем использовать класс ExceptionFilterAttribute:
using System; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web.Http.Filters; namespace WebApiApp.Filters { public class CustomExceptionAttribute : ExceptionFilterAttribute { public Type ExceptionType { get; set; } public string Message { get; set; } public HttpStatusCode StatusCode { get; set; } public override Task OnExceptionAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { if (actionExecutedContext.Exception != null && actionExecutedContext.Exception.GetType() == ExceptionType) { actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(StatusCode, Message); } return Task.FromResult<object>(null); } } }
Чтобы определить обработку исключения, надо переопределить метод OnExceptionAsync()
. И в отличие от ранее определенного фильтра
исключений, в данном случае мы не привязаны к конкретному типу исключений, к конкретному сообщению или статусному коду, которые отправляются в ответ
пользователю. Все эти данные мы можем задать в зависимости от ситуации при использовании атрибута.
Применим фильтр:
[CustomException(ExceptionType = typeof(IndexOutOfRangeException), StatusCode = HttpStatusCode.BadRequest, Message = "Элемент вне диапазона")] public string Get(int id) { string[] letters = new string[] { "aab", "aba", "baa" }; return letters[id]; }