Asp.net mvc framework
Шрифт:
<legend>Данные</legend>
<label for="email">Email</label>
<%=Html.TextBox("email", user.Email)%>
<label for="isApproved"><%=Html.CheckBox("isApproved",
user.IsApproved)%>подтвержден</label>
<label for="isLockedOut"><%=Html.CheckBox("isLockedOut",
user.IsLockedOut)%>заблокирован</label>
</fieldset>
<input type="submit" value="Сохранить" />
<%=Html.ActionLink("Удалить", "Delete", new {userId = (Guid)
user.ProviderUserKey})%>
<% } %>
</asp:Content>
Когда
Рис. 4.7. Форма редактирования данных пользователя
C помощью этой формы и действий, реализованных в нашем контроллере, вы сможете модифицировать данные пользователя либо удалить его из системы.
Архитектура контроллеров
Мы рассмотрели простейший вариант создания контроллеров и их действий, а также сопоставленных с ними представлений. Но архитектура MVC Framework помимо рассмотренных механизмов содержит массу больших и малых механизмов, которые позволяют регулировать контроллеры, управлять вызовами кода, защищать контроллеры и действия от нежелательных вызовов, формировать базовые архитектуры для набора действий или даже группы контроллеров.
Далее мы более подробно рассмотрим архитектуру реализации контроллеров в MVC Framework. По мере рассмотрения, наш простейший код будет видоизменяться согласно новым техникам, о которых будет идти рассказ.
Порядок вызова архитектурных механизмов
ASP.NET MVC реализует следующий порядок выполнения внутренних механизмов:
1. При первом обращении к приложению в Global.asax производится регистрация маршрутов механизма маршрутизации ASP.NET в специальном объекте RouteTable.
2. С помощью urlRoutingModule производится маршрутизация запроса с использованием созданных маршрутов, при этом выбирается первый подходящий маршрут, после чего создается объект типа RequestContext.
3. Обработчик MvcHandler, с помощью данных полученного объекта RequestContext, инстанцирует объект фабрики контроллеров типа IControllerFactory. Если он не был задан специально, по умолчанию инстанцируется объект класса DafaultControllerFactory.
4. В фабрике контроллеров вызывается метод GetControllerInstance, который принимает параметр в виде типа необходимого контроллера. Этот метод возвращает инстанцированный объект необходимого контроллера.
5. У полученного объекта контроллера вызывается метод Execute, которому передается объект RequestContext.
6. С помощью ActionInvoker, свойства класса Controller типа ControllerActionInvoker, определяется необходимое действие и выполняется его код. Если ActionInvoker специально не сопоставлен, то используется свойство ActionInvoker по умолчанию. Для инициализации параметров действия используется механизм Model Binding, который может быть переопределен.
7. Определение действия может быть изменено в случае, когда пользователь определил для действий атрибуты типа ActionMethodSelectorAttribute.
Для каждого такого атрибута вызывается метод IsValidForRequest, которому передается набор параметров типа ControllerContext и MethodInfo. Метод IsValidForRequest возвращает результат в виде bool, который определяет, подходит ли выбранное действие для исполнения в контексте запроса.8. Выполнение действия может быть отменено, изменено или пропущено, если пользователь определил для действия атрибуты типа FilterAttibute. Такие атрибуты могут использоваться для определения прав доступа, кэширования результатов, обработки исключений.
9. В случае когда для действия определены атрибуты типа ActionFilterAttribute, то выполнение действия может быть изменено таким атрибутом на следующих этапах: перед выполнением действия, после выполнения действия, перед исполнением результата или после исполнения результата действия.
10. В случае когда Actioninvoker был специально переопределен, то после вызова действия результат действия передается методу CreateActionResult свойства Actioninvoker, который волен переопределить возвращаемый результат действия и вернуть результат типа ActionResult.
11. В случае, когда Actioninvoker не был переопределен, действие должно вернуть результат выполнения в виде ActionResult.
12. Для результата типа ActionResult вызывается метод ExecuteResult, который осуществляет отображение результата для контекста запроса. Создав свой вариант класса, наследующий ActionResult и реализующий ExecuteResult, можно переопределить действие и возвращать результат в нужном виде, например, формировать RSS-ленту.
Рассмотрим все шаги, относящиеся к контроллерам и действиям, более подробно. Для этого выделим основные темы:
? фабрика контроллеров;
? действия, фильтры и атрибуты;
? механизм Model Binding.
Фабрика контроллеров
После того как внутренний механизм MVC получит запрос, обработает таблицу маршрутизации и подберет необходимый маршрут, в дело вступает фабрика контроллеров. По умолчанию создается и используется экземпляр фабрики контроллеров типа DefaultFactoryController. Для реализации своего варианта поведения фабрики контроллеров разработчик может реализовать свой класс, наследующий класс DefaultFactoryController.
Фабрика контроллеров — это механизм, созданный с одной целью — создавать экземпляры контроллеров. В ASP.NET MVC фабрика контроллеров — это один из механизмов, который позволяет настроить поведение механизма MVC под себя, расширить функционал, предоставить разработчику возможность гибкой настройки действия MVC.
Фабрика контроллеров в ASP.NET реализует интерфейс IControllerFactory, который содержит всего два метода:
public interface IControllerFactory {
IController CreateController(RequestContext requestContext,
string controllerName);
void ReleaseController(IController controller);
}
Здесь CreateController должен создавать экземпляр контроллера, а ReleaseController — разрушать его или проводить какие-то другие действия после завершения работы контроллера. Вы можете создать свою фабрику контроллеров, реализовав этот интерфейс. Но более простым способом расширения фабрики является ее реализация с помощью наследования от класса DefaultFactoryController.
Для примера рассмотрим такую, вполне возможную задачу, решить которую позволит фабрика контроллеров: