Фильтры исключений

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core

Последнее обновление: 29.10.2015

Фильтры исключений позволяют обработать исключения, возникшие в методе во время выполнения запроса. Все фильтры исключений реализуют интерфейс 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, то пользователь увидит в браузере сообщение об ошибке от фильтра исключений:

Обработка исключений в Web API

ExceptionFilterAttribute

Кроме прямой реализации интерфейса 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];
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850