Главная страница   /   16.1. Использование фильтров (ASP.NET MVC 4

ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

16.1. Использование фильтров

Вы уже видели пример фильтра в главе 11, когда мы применили авторизацию к контроллеру администрирования SportsStore. Мы хотели, чтобы данный метод действия использовался только прошедшими аутентификацию пользователями, и это можно было бы реализовать несколькими способами. Например, можно проверять статус авторизированности запроса в каждом методе действия, как показано в листинге 16-1.

Листинг 16-1: Явная проверка авторизации в методах действия
namespace SportsStore.WebUI.Controllers
{
	public class AdminController : Controller
	{
		// ... instance variables and constructor
		public ViewResult Index()
		{
			if (!Request.IsAuthenticated)
			{
				FormsAuthentication.RedirectToLoginPage();
			}
			// ...rest of action method
		}
		public ViewResult Create()
		{
			if (!Request.IsAuthenticated)
			{
				FormsAuthentication.RedirectToLoginPage();
			}
			// ...rest of action method
		}
		public ViewResult Edit(int productId)
		{
			if (!Request.IsAuthenticated)
			{
				FormsAuthentication.RedirectToLoginPage();
			}
			// ...rest of action method
		}
		// ... other action methods
	}
}

Как видите, при таком подходе много повторов, и вместо этого разумнее использовать фильтр, как показано в листинге 16-2.

Листинг 16-2: Применяем фильтр
namespace SportsStore.WebUI.Controllers
{
	[Authorize]
	public class AdminController : Controller
	{
		// ... instance variables and constructor
		public ViewResult Index()
		{
			// ...rest of action method
		}
		public ViewResult Create()
		{
			// ...rest of action method
		}
		public ViewResult Edit(int productId)
		{
			// ...rest of action method
		}
		// ... other action methods
	}
}

Фильтры – это атрибуты .NET, которые добавляют дополнительные этапы в конвейер обработки запроса. В листинге 16-2 мы использовали фильтр Authorize, который имеет тот же эффект, как и все дублирующиеся проверки в листинге 16-1.

Памятка по атрибутам .NET

Атрибуты - это специальные классы .NET, наследующие от System.Attribute. Вы можете применить их к другим элементам кода, в том числе классам, методам, свойствам и полям. Их цель состоит в том, чтобы внедрить дополнительную информацию в скомпилированный код, которую можно позже прочитать в среде выполнения.

В C# для применения атрибутов используются квадратные скобки, а заполнить их общедоступные свойства можно путем присвоения значений параметрам (например, [MyAttribute(SomeProperty=value)]). Согласно соглашению по именам компилятора C#, если имя класса атрибута заканчивается на Attribute, эту часть можно опустить (например, применить фильтр AuthorizeAttribute можно, записав только [Authorize]).

Четыре основных типа фильтров

MVC Framework поддерживает четыре типа фильтров, которые позволяют внедрять логику в разное время процесса обработки запроса. Они описаны в таблице 16-1.

Таблица 16-1: Типы фильтров MVC Framework
Тип фильтра Интерфейс Реализация по умолчанию Описание
Фильтр авторизации IAuthorizationFilter AuthorizeAttribute Запускается вначале, перед любым другим фильтром или методом действия
Фильтр действий IActionFilter ActionFilterAttribute Запускается до и после метода действия
Фильтр результатов IResultFilter ActionFilterAttribute Запускается до и после выполнения результата действия
Фильтр исключений IExceptionFilter HandleErrorAttribute Запускается только в том случае, если другой фильтр, метод действия или результат действия генерирует исключение

Перед тем, как вызвать действие, MVC Framework проверяет определение метода на наличие атрибутов, реализующих перечисленные в таблице 16-1 интерфейсы. Если они есть, то в соответствующий момент обработки запроса вызывается метод, определенный этим интерфейсом. Платформа включает стандартные классы атрибутов, которые реализуют интерфейсы фильтров. Позже в данной главе мы научимся использовать эти классы.

Примечание

Класс ActionFilterAttribute реализует и интерфейс IActionFilter, и IResultFilter. Этот класс является абстрактным, что подразумевает необходимость его реализовать. Другие классы с полезными функциями, такие как AuthorizeAttribute и HandleErrorAttribute, можно использовать, не создавая производный класс.

Применяем фильтры к контроллерам и методам действий

Фильтры можно применить к отдельным методам действий или к целому контроллеру. В листинге 16-2 мы применили фильтр Authorize к классу AdminController. Это имеет тот же эффект, как и применение его к каждому методу действия в контроллере, что показано в листинге 16-3.

Листинг 16-3: Применяем фильтр к методам действий индивидуально
namespace SportsStore.WebUI.Controllers
{
	public class AdminController : Controller
	{
		// ... instance variables and constructor
		[Authorize]
		public ViewResult Index()
		{
			// ...rest of action method
		}

		[Authorize]
		public ViewResult Create()
		{
			// ...rest of action method
		}
		// ... other action methods
	}
}

Вы можете одновременно применить несколько фильтров, причем на разных уровнях, то есть и к контроллеру, и отдельному методу действия. В листинге 16-4 показано использование трех различных фильтров.

Листинг 16-4: Применяем несколько фильтров в классе контроллера
[Authorize(Roles = "trader")] // applies to all actions
public class ExampleController : Controller
{
	[ShowMessage] // applies to just this action
	[OutputCache(Duration = 60)] // applies to just this action
	public ActionResult Index()
	{
		// ... action method body
	}
}

Некоторые фильтры из листинга 16-4 принимают параметры. Мы рассмотрим, как они работают, когда будем изучать виды фильтров по отдельности.

Примечание

Если вы определили пользовательский базовый класс для контроллеров, фильтры, примененные к базовому классу, будут использоваться и в производных классах.