Предыдущий ролик Следующий ролик  

Видео урок: Using filters

Основы ASP.NET MVC 5

Еще один способ модификации действий в ASP.NET MVC - при помощи фильтров. Существует несколько типов фильтров. Мы рассмотрим несколько наиболее часто используемых фильтров в том порядке, в котором они применяются во время выполнения приложения. Фильтр авторизации позволяет указывать, какие пользователи или группы пользователей имеют доступ к конкретному методу или контроллеру. Один из примеров фильтра авторизации - встроенный атрибут Authorize. Атрибут Authorize может принимать несколько необязательных параметров, в том числе, список ролей и список пользователей, которым разрешено выполнять указанное действие.

Обратите внимание, что этот атрибут можно разместить прямо над селектором действия HttpPost. В этом примере мы указываем, что данное действие может выполнять любой пользователь, наделенный ролью администратора, а также пользователь J. Smith независимо от той роли, которой он или она наделены. Если вы хотите, чтобы выполнять действие мог любой зарегистрированный пользователь, а неизвестные посетители получали отказ в доступе, используйте атрибут Authorize без параметров. Такие атрибуты можно использовать и для выделения класса контроллера. В этом примере для всех методов контроллера CustomerController необходима аутентификация.

Если вы обнаружите, что есть какие-то исключения и вам нужно переопределить это на уровне действий, можете воспользоваться атрибутом AllowAnonymous. Я хочу вкратце упомянуть о том, что помимо авторизации управлять аутентификацией на уровне контроллеров или действий можно и с помощью фильтра аутентификации, который впервые появился в MVC5. Но когда мы дойдем до обсуждения безопасности, мы будем рассматривать лишь более общепринятую аутентификацию на уровне приложений. Еще один тип фильтра - фильтр действий. Это как раз тот момент, когда терминология иногда сбивает с толку.

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

Затем переопределите метод OnActionExecuting, отвечающий за код, который должен выполняться перед действием, или метод OnActionExecuted, соответствующий коду, который будет выполняться после действия. Вот так это должно выглядеть. Предположим, что мне захотелось создать фильтр, который будет регистрировать все успешные запросы действия, к которому он применяется. Переопределим метод OnActionExecuted таким образом, чтобы он запускался после окончания выполнения действия. В этом методе используется объект filterContext. Я могу вытащить IP-адрес пользователя и передать его в свой пользовательский метод logRequest.

Кроме того, нужно не забыть в конце вызвать метод OnActionExecuted для класса base. Затем можно просто применить этот фильтр к данному действию или ко всему контроллеру с помощью атрибута MyLoggingFilter. Заметьте, что слово "attribute" добавлять необязательно, даже если оно используется в имени класса. Еще можно применить фильтр глобально ко всем действиям приложения. Для этого найдите в папке App_Start файл FilterConfig.

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

Таким образом, если у вас несколько параметров, то можно указать их здесь в виде списка, элементы которого разделены точкой с запятой. Наконец, существуют фильтры исключений, которые запускаются, если во время выполнения действия выдаются необработанные исключения. Один из примеров такого фильтра - атрибут HandleError. Мы видели, что он уже применяется в шаблоне нашего проекта в качестве глобального фильтра. Предполагается, что результатом применения этого атрибута будет перенаправление пользователя на представление Error, которое находится в папке Views -> Shared и обладает доступом к информации о соответствующей ошибке.

Давайте посмотрим, что произойдет, если изменить метод Index таким образом, чтобы в первую очередь он выдавал исключение "Stack overflow". Давайте запустим приложение без отладки по клавише Ctrl+F5. Это определенно не то представление Error, которое мы только что рассматривали. Так что же происходит? По умолчанию если запрос поступает от того же сервера, на котором запускается приложение, то предполагается, что показ подробной информации об ошибке не принесет никакого вреда. Итак, получаем так называемый "желтый экран смерти", на котором действительно демонстрируется некоторый фрагмент нашего кода.

Если вам хочется посмотреть, что увидит удаленный пользователь, а не разработчик, работающий на том же самом сервере, то нужно перейти к файлу Web.config и добавить элемент customErrors в элемент system.web. По умолчанию параметр mode имеет значение RemoteOnly, что подразумевает показ пользовательской страницы с ошибкой для удаленных пользователей и желтый экран смерти с подробной информацией для локальных пользователей. Но установив значение "On", мы можем принудительно показать пользовательскую страницу с ошибкой. После редактирования файла Web.config и сохранения изменений необходимо просто обновить страницу и в результате мы увидим представление Error.

Даже если этот фильтр уже применяется глобально, вам все равно может понадобиться применить его к определенному методу или контроллеру, чтобы задать другое представление с помощью параметра View. Вы также можете указывать для разных типов исключений разные представления Error. В этом примере используется исключение "Divide by zero" (Деление на ноль), которое вызовет показ представления MathError, и исключение "Stack overflow", вызывающее показ представления SOError. Все остальные типы исключений будут вызывать показ представления Error, поскольку оно будет отбираться глобальным фильтром HandleError.

Это видео является своего рода введением в концепцию фильтров MVC, поскольку в нем рассматриваются наиболее часто используемые на сегодняшний момент фильтры. Все внесенные мною изменения в этот проект доступны в файлах упражнений, находящихся в папке "Chapter 1" каталога Final. Позднее мы более подробно рассмотрим эти и другие фильтры.