Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Фильтры исключений срабатывают, если при выполнении метода действия будет выброшено необработанное исключение.
С одной стороны, мы могли поместить всю логику выполнения метода в блок 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.htm.
Подобным образом мы можем обработать и другие типы исключений.
Создавать свои фильтры исключений необязательно, так как во фреймворке имеется встроенная реализация интерфейса IExceptionFilter - атрибут HandleErrorAttribute. Он имеет ряд свойств, с помощью которых мы можем произвести гибкую настройку фильтра:
Свойство | Тип | Описание |
ExceptionType | Type | Представляет тип обрабатываемого исключения. По умолчанию используется
|
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>