1. Проверяем, не передается ли в фабрику контроллера типа контроллера в виде null, если это так, то завершаем выполнение вызовом базового метода для выполнения действия по умолчанию.
2. Загружаем наш XML-файл с "черным списком" и ищем в нем имя типа контроллера, который запрошен для создания.
3. Если в "черном списке" существует запись о блокировании данного контроллера, то возвращаем ответ на запрос в виде 404 ошибки HTTP "Страница не найдена".
4. Если контроллер отсутствует в "черном списке", то мы выполняем базовое действие по умолчанию для поиска и создания необходимого контроллера.
Для того чтобы наш код заработал, мы должны зарегистрировать нашу фабрику контроллеров. Функцию регистрации выполняет метод SetControllerFactory
класса controllerBuilder
. Добавим его вызов в файл Global.asax:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory( new ControllerFactory());
}
После этого попробуем запустить наше приложение. Главная страница запустится нормально, т. к. она создается с помощью контроллера HomeController
. Но если мы попробуем перейти на страницу входа, регистрации или административную страницу, то увидим стандартное сообщение браузера о том, что страница не была найдена.
Другим, пожалуй, самым распространенным вариантом использования фабрики контроллеров является реализация архитектурного паттерна Инверсия контроля (Inversion of Control), который в данном применении позволяет в приложении уменьшить зависимость и ослабить связи между контроллерами. Для реализации такого механизма используются сторонние библиотеки, вроде Unity Application Blocks от Microsoft, Spring.NET или Ninject .
Действия, фильтры и атрибуты
Переопределение свойства Actionlnvoker
После того как фабрика контроллеров создала контроллер, производится вызов его метода Execute
, который с помощью специального свойства ActionInvoker
определяет необходимый метод для выполнения действия и вызывает его. По умолчанию ActionInvoker
создается как экземпляр класса ControllerActionInvoker
, но разработчик волен переопределить его. Переопределение ActionInvoker
— это еще одна точка расширения ASP.NET MVC, которой вы можете воспользоваться для самых разнообразных целей. Например, т. к. именно ActionInvoker
исполняет все необходимые фильтры типа ActionFilter
, то вы вольны изменить этот механизм для того, чтобы часть фильтров не могла быть использована для ваших контроллеров в некотором гипотетическом случае.
По умолчанию метод InvokeAction
класса ActionInvoker
вместе с самим вызовом действия реализует механизм обработки заданных через атрибуты фильтров для действия.
Всего InvokeAction
формирует четыре группы фильтров:
□ ActionFilters
— вызываются во время исполнения действия;
□ ResultFilters
— вызываются после исполнения действия при обработке результата;
□ AuthorizationFilters
— вызываются до исполнения действия, чтобы произвести проверку доступа;
□ ExceptionFilters
— вызываются во время обработки возникшего исключения.
Существуют такие действия, скорость вызова которых критически важна. В связи с этим лишние операции по поиску и исполнению фильтров типа ActionFilter
могут отрицательно сказаться на производительности, даже когда никаких фильтров не используется. Поэтому создание своего варианта класса ActionInvoker
и метода InvokeAction
имеет смысл и может быть полезно. Вы можете реализовать InvokeAction
в таком виде, в котором и производительность будет на высоте, и необходимый функционал не будет потерян.
Для примера рассмотрим листинг 4.2 с реализацией такого класса ActionInvoker
, который максимально быстро вызывает действие контроллера без поддержки каких-либо атрибутов и накладных расходов на такую поддержку.
Листинг 4.2
public class FastControllerActionInvoker : ControllerActionInvoker
{
public override bool InvokeAction(
ControllerContext controllerContext, string actionName)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (String.IsNullOrEmpty(actionName))
throw new ArgumentException("actionName");
ControllerDescriptor controllerDescriptor =
GetControllerDescriptor(controllerContext);
ActionDescriptor actionDescriptor = FindAction(controllerContext,
controllerDescriptor, actionName);
if (actionDescriptor != null)
{
IDictionary parameters =
GetParameterValues(controllerContext, actionDescriptor);
var actionResult = InvokeActionMethod(controllerContext,
actionDescriptor, parameters);
InvokeActionResult(controllerContext, actionResult);
Читать дальше
Конец ознакомительного отрывка
Купить книгу