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

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

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

Фильтры исключений срабатывают, если при выполнении метода действия будет выброшено необработанное исключение.

С одной стороны, мы могли поместить всю логику выполнения метода в блок try...catch и отследить исключение. Однако область работы фильтров исключения несколько шире. Они позволяют отследить не только исключения, возникающие в самом методе, но исключения, генерируемые результатами действий, а также другими применяемыми к данному действию фильтрами. В этом и состоит мощь данного типа фильтров.

Все фильтры исключений должны применять интерфейс IExceptionFilter:

public interface IExceptionFilter
{
	void OnException(ExceptionContext filterContext);
}

И если вдруг приложение выбрасывает необрабатываемое исключение, то фильтр вызывает метод OnException.

Передаваемый в этот метод параметр - ExceptionContext является объектом, производным от ControllerContext. Поэтому из него можно извлечь как специфичную для фильтра информацию, так и общую информацию о запросе.

В частности класс ExceptionContext обладает следующими свойствами, которые позволяют получить информацию об исключении:

Свойство

Тип

Описание

ActionDescriptor

ActionDescriptor

Содержит информацию о методе действия, на котором было выброшено исключение

Exception

Exception

Представляет само необработанное исключение

ExceptionHandled

bool

Значение, показывающее, считается ли исключение обработанным. Если мы на фильтре помечаем его значение в true, то исключение считается обработанным

Result

ActionResult

Результат метода действия, к которому применяется фильтр исключения

С помощью свойства Exception мы можем получить доступ к выбрасываемому исключению.

Установив свойство ExceptionHandled в true, фильтр тем самым помечает исключение как обработанное.

С помощью свойства Result фильтр управляет результатом действий. Общераспространенной практикой в данном случае является перенаправление пользователя на страницу ошибки или отображение ошибки на экране.

Теперь создадим простенький фильтр, который будет обрабатывать исключение IndexOutOfRangeException:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Filters.Filters
{
    public class IndexException : FilterAttribute, IExceptionFilter
    {

        public void OnException(ExceptionContext exceptionContext)
        {
            if (!exceptionContext.ExceptionHandled && exceptionContext.Exception is IndexOutOfRangeException)
            {
                exceptionContext.Result = new RedirectResult("/Content/ExceptionFound.html");
                exceptionContext.ExceptionHandled = true;
            }
        }
    }
}

Здесь в методе OnException первым делом мы проверяем, не установлено ли значение свойства ExceptionHandled. Если оно установлено в true, следовательно, какой-то другой фильтр исключений уже обработал данное исключение. Также проверяется тип исключения. Поскольку мы ловим в данном случае только исключения типа IndexOutOfRangeException, следовательно, нас только они интересуют.

Далее мы устанавливаем результат метода, к которому применен фильтр. Предполагается, что в проекте в каталоге Content у нас находится некоторая страница ExceptionFound.html, которая отображает пользователю сообщение об ошибке.

В данном случае важно пометить исключение как обработанное: exceptionContext.ExceptionHandled = true. Иначе, если мы этого не сделаем, то мы можем увидеть в браузере все диагностическое сообщение об ошибке, которое обычно посылает фреймворк в ответ клиенту.

Пример использования:

[IndexException]
public ActionResult Index()
{
    int[] mas = new int[2];
    mas[6] = 4;
    return View();
}

В данном случае метод Index выбросит необработанное исключение, и оно будет объектом типа IndexOutOfRangeException, а пользователь будет перенаправлен на страницу ExceptionFound.html.

Подобным образом мы можем обработать и другие типы исключений.

HandleErrorAttribute. Встроенная обработка исключений.

Создавать свои фильтры исключений необязательно, так как во фреймворке имеется встроенная реализация интерфейса IExceptionFilter - атрибут HandleErrorAttribute. Он имеет ряд свойств, с помощью которых мы можем произвести гибкую настройку фильтра:

Свойство

Тип

Описание

ExceptionType

Type

Представляет тип обрабатываемого исключения. По умолчанию используется System.Exception

View

string

Имя представления, которое рендерится данным фильтром. Если значение не задано, то по умолчанию используются следующие пути: /Views/Имя_контроллера/Error.cshtml или /Views/Shared/Error.cshtml

Master

string

Имя используемой мастер-страницы

При обработке исключения фильтр исключений посылает статусный код HTTP 500 и генерирует указанное в свойстве View представление. Например, используем предыдущий пример с фильтром исключений, применив встроенную реализацию:

[HandleError(ExceptionType = typeof(System.IndexOutOfRangeException), View = "ExceptionFound")]
public ActionResult About()
{
    int[] mas = new int[2];
    mas[6] = 4;
    return View();
}

В данном случае очевидно, что на строке mas[6] = 4; будет выброшено исключение. В режиме отладки у вас приостановится выполнение программы, тогда вы можете нажать на кнопку Continue на панели инструментов. Здесь опять мы обрабатываем исключение типа IndexOutOfRangeException, и при возникновении такового генерируем в ответ представление ExceptionFound.cshtml. Данное представление должно находиться в проекте в каталоге Views/Имя_контроллера/.

Сразу надо сказать, что если вы хотите при разработке видеть обрабатываемые фильтром HandleErrorAttribute, то надо включить данную функциональность в файле конфигурации web.config с помощью тега <customErrors mode="On" />:

<system.web>
    <customErrors mode="On"  />
	
	<!-- далее остальное содержание узла system.web -->
</system.web>
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850