Использование фильтров для методов действий
Фильтры действий можно использовать для различных целей. Встроенный класс для создания таких фильтров, IActionFilter
, показан в листинге 16-21.
Листинг 16-21: Интерфейс IActionFilter
namespace System.Web.Mvc
{
public interface IActionFilter
{
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActionExecutedContext filterContext);
}
}
Этот интерфейс определяет два метода. MVC Framework вызывает метод OnActionExecuting
перед тем, как вызвать метод действия, и OnActionExecuted
после вызова метода действия.
Реализуем метод OnActionExecuting
Метод OnActionExecuting
вызывается до метода действия. Вы можете использовать его для того, чтобы изучить запрос и принять решение о его отмене, изменении или задержке его выполнения. Параметром этого метода является объект ActionExecutingContext
, который создает подкласс класса ControllerContext
и определяет два дополнительных свойства, описанных в таблице 16-7.
Таблица 16-7: Свойства ActionExecutingContext
Название | Тип | Описание |
ActionDescriptor |
ActionDescriptor |
Предоставляет информацию о методе действия |
Result |
ActionResult |
Результат для метода действия; фильтр может отменить запрос, установив данному свойству иное значение, кроме null
|
Вы можете использовать фильтр, чтобы отменить запрос, определив в качестве значения для свойства Result
результат действия. Чтобы это продемонстрировать, мы создали свой собственный класс фильтра действий под названием CustomActionAttribute
в папке Infrastructure
, как показано в листинге 16-22.
Листинг 16-22: Отмена запроса в методе OnActionExecuting
using System.Web.Mvc;
namespace Filters.Infrastructure
{
public class CustomActionAttribute : FilterAttribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.IsLocal)
{
filterContext.Result = new HttpNotFoundResult();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
// not yet implemented
}
}
}
В этом примере мы используем метод OnActionExecuting
, чтобы проверить, отправлен ли запрос с локальной машины. Если это так, то возвращаем пользователю ответ 404 — Not Found
.
Примечание
Как вы видите из листинга 16-22, необязательно реализовывать оба метода, определенные в интерфейсе
IActionFilter
, чтобы создать рабочий фильтр. Будьте осторожны, чтобы не вызватьNotImplementedException
, которое Visual Studio добавляет к классу при реализации данного интерфейса. В фильтре действий MVC Framework вызывает оба метода, и если возникает исключение, то будут инициированы фильтры исключений. Если вам не нужно добавлять к методу какую-либо логику, просто оставьте его пустым.
Фильтр действий применяется так же, как и любой другой атрибут. Чтобы продемонстрировать фильтр, который мы создали в листинге 16-22, мы добавили новый метод действия в контроллер Home
, как показано в листинге 16-23.
Листинг 16-23: Добавляем новое действие в контроллер Home
[CustomAction]
public string FilterTest()
{
return "This is the FilterTest action";
}
Вы можете протестировать фильтр, запустив приложение и перейдя по ссылке /Home/FilterTest
. Если вы отправили запрос с локальной машины, то вы увидите результат, показанный на рисунке 16-7, хотя, как мы знаем, и контроллер, и действие существуют.
Рисунок 16-7: Эффект от использования фильтра действий

Реализуем метод OnActionExecuted
Фильтр также можно использовать для выполнения каких-либо задач, которые измеряют время выполнения метода действия. В качестве простого примера мы создали новый класс ProfileActionAttribute
в папке Infrastructure
, который измеряет количество времени, которое занимает выполнение метода действия. Код этого фильтра показан в листинге 16-24.
Листинг 16-24: Более сложный фильтр действий
using System.Diagnostics;
using System.Web.Mvc;
namespace Filters.Infrastructure
{
public class ProfileActionAttribute : FilterAttribute, IActionFilter
{
private Stopwatch timer;
public void OnActionExecuting(ActionExecutingContext filterContext)
{
timer = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
timer.Stop();
if (filterContext.Exception == null)
{
filterContext.HttpContext.Response.Write(
string.Format("<div>Action method elapsed time: {0}</div>",
timer.Elapsed.TotalSeconds));
}
}
}
}
В этом примере мы запускаем таймер с помощью метода OnActionExecuting
(используется класс таймера Stopwatch
из пространства имен System.Diagnostics
). Метод OnActionExecuted
вызывается по завершении метода действия. В листинге 16-25 показано, как мы применили атрибут к контроллеру Home
(ранее созданный фильтр был удален, чтобы локальные запросы не перенаправлялись).
Листинг 16-25: Применяем фильтр действий к контроллеру Home
[ProfileAction]
public string FilterTest()
{
return "This is the ActionFilterTest action";
}
Если вы запустите приложение и перейдете по ссылке /Home/FilterTest
, то увидите те же результаты, что и на рисунке 16-8.
Рисунок 16-8: Используем фильтр действий для измерения производительности

Подсказка
Обратите внимание, что информация о производительности отображается в браузере перед результатом метода действия. Так происходит потому, что фильтр действий выполняется после завершения метода действия, но до обработки результата.
В качестве параметра в метод OnActionExecuted
передается объект ActionExecutedContext
. Этот класс определяет дополнительные свойства, которые показаны в таблице 16-8. Свойство Exception
возвращает любое исключение, выброшенное методом действия, а свойство ExceptionHandled
указывает, было ли оно обработано другим фильтром.
Таблица 16-8: Свойства ActionExecutedContext
Название | Тип | Описание |
ActionDescriptor |
ActionDescriptor |
Предоставляет информацию о методе действия |
Canceled |
bool |
Возвращает true , если действие было отменено другим фильтром
|
Exception |
Exception |
Возвращает исключение, выброшенное другим фильтром или методом действия |
ExceptionHandled |
bool |
Возвращает true , если исключение было обработано
|
Result |
ActionResult |
Результат для метода действия; фильтр может отменить запрос, установив для этого свойства иное значение, кроме null
|
Свойство Canceled
возвращает true
, если запрос был отменен другим фильтром (т.е. он установил значение для свойства Result
) с того момента, когда был запущен метод фильтра OnActionExecuting
. Метод OnActionExecuted
все равно будет вызван, но только для того, чтобы можно было освободить или очистить ранее используемые ресурсы.