Pull to refresh

Ставим точки в MVC Framework. Механизм работы, часть вторая

Reading time 4 min
Views 4.3K
Это третья статья из цикла статей про MVC Framework. В первой я постарался дать ответ на вопрос “Зачем нужен MVC Framework?”, а во второй начал рассказ о том, как он устроен. Рассказ в предыдущей статье подразумевал поверхностное описание всего процесса работы MVC Framework без углубления в детали. Детали последуют позднее в ходе цикла статей. Эта статья продолжит рассказ про внутренний механизм работы MVC Framework, который был прерван на описании Model Binding. C него и начнем.

Model Binding


Когда механизм MVC Framework определил класс контроллера и метод действия в нем, которые должны участвовать в формировании ответа на клиентский запрос встает задача передать параметры запроса действию. В простейшем случае, передача данных осуществляет путем сопоставления параметров запроса с параметрами метода. Так например, если пользователь отправил форму с данными через заполнение определенных html-элементов, то значения содержимого этих элементов будет передано действию через одноименный параметр метода. Данные textarea с атрибутом name равным address будут сопоставлены с параметром метода действия определенным как string address.

Таким сопоставлением занимается механизм Model Binding, но его возможности на таком простом примере не заканчиваются. Что делать, когда параметров на форме несколько десятков? Не станем же мы создавать методы с двумя десятками параметров, только для того, чтобы получить данные с формы. Действительно, делать этого не нужно. Model Binding предоставляет замечательную возможность переопределить порядок сопоставления параметров и сделать инициализацию не в виде “параметр формы = параметр метода”, а сложнее. Например, мы можем определить класс или структуру, которые будут содержать данные формы и в методе определить только один параметр в виде экземпляра этой структуры. Затем определив механизм Model Binding для нашего комплексного типа мы можем инициализировать его свойства параметрами запроса и вызвать метод действия, передав ему инициализированный объект. В итоге, многочисленные параметры на форме передадутся в метод действия в виде экземпляра класса с заполненными свойствами. Очень удобно.

Но разработчику MVC Framework даже этого делать не нужно, поскольку в MVC Framework реализован класс DefaultModelBinder, который делает всю работу по сопоставлению параметров запроса комплексным типам. Однако, это не мешает вам определить свой собственный механизм Model Binding для определенных типов параметров. Это может быть полезно, когда кроме простой передачи данных из запроса, вы захотите произвести еще какие-нибудь действия с экземпляром комплексного типа.

У приложения MVC Framework есть стандартное свойство ModelBinders, которое содержит коллекцию определенных пользователем механизмов сопоставления параметров. Эти механизмы представляют собой реализацию интерфейса IModelBinder, который содержит только один метод BindModel со следующим определением:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);

Используя передаваемый механизмом MVC Framework параметр controllerContext, разработчик может получит доступ ко всем данным контекста запроса, в том числе к параметрам. Механизм MVC Framework ожидает от реализации интерфейса IModelBinder объекта, который бы определял результат сопоставления параметров запроса для конкретного комплексного типа, к которому применяется атрибут. Регистрация своего механизма Model Binding производится в global.asax в методе Application_Start следующим образом:

ModelBinders.Binders.Add(typeof(UserData), new UserDataBinder());

где, typeof(UserData) – указание для какого комплексного типа создается механизм сопоставления, new UserDataBinder() – экземпляр класс реализующего IModelBinder.

Примечание. Для того, чтобы использовать эти механизмы не глобально, а только локально, одноразово, разработчик, вместо регистрации глобального механизма Model Binding, может пометить требуемый параметр действия атрибутом ModelBinder, который содержит параметр определяющий тип механизма. Как это делается, показано ниже:

public ActionResult Update([ModelBinder(typeof(UserDataBinder))] UserData userData);

Когда MVC Framework вызывает метод действия, то для каждого параметра комплексного типа, он ищет в коллекции ModelBinders механизм Model Binding и вызывает его, если он есть. После этого, пользовательская реализация сопоставления параметров формирует объект который приводится к типу параметра и передается при вызове действия. В случае, когда пользовательской реализации для комплексного типа нет, в дело вступает механизм сопоставления параметров по умолчанию, который реализуется через DefaultModelBinder.

Разработчик может еще более гибко настроить выполнение сопоставления параметров используя атрибут BindAttribute, который позволяет определить несколько правил сопоставления:
  • префикс используемый в разметке для сопоставления по умолчанию;
  • белые и черные списки имен параметров.

Более подробно работа этого атрибута будет рассмотрена в следующих статьях.

После того, как все параметры будут сопоставлены механизм ActionInvoker вызывает метод действия, который выполняет логику действия и, по правилам MVC Framework, должен вернуть результат в виде ActionResult или его производных.

Исполнение результата и ActionResult


Итак, действие было вызвано и вернуло результат в виде ActionResult или его производных. Вообще, механизм MVC Framework содержит целый ряд таких производных класса ActionResult: ViewResult, JsonResult, FileResult, RedirectResult, RedirectToRouteResult, ContentResult, EmptyResult. Уже по названию можно определить назначения каждого их них. Каждый из таких типов результата действия отражает результат, который будет возвращен клиенту в ответ на запрос. Важно отметить, что действие не занимается записью в поток результата, формированием разметки или другими действиями по отправки результата. Все действия MVC Framework возвращают данные в виде определенного механизма ActionResult, который в свою очередь и делает все необходимое, чтобы клиент получил данные в нужном виде. Это называется исполнением результата.

Более подробно про работу ActionResult и назначение всех его производных будет освещено в последующих статьях.

Самое мощное средство MVC Framework заключается в том, что разработчик может определить свой вариант реализации ActionResult для формирования своего собственного результата в ответ на запрос клиента. Так очень легко может быть реализован вариант ActionResult, который возвращает RSS-поток.

Получив от действия результат в виде ActionResult, механизм MVC Framework (в лице ActionInvoker) вызывает метод ExecuteResult, который и выполняет всю работу по формированию разметки, форматированию данных, созданию заголовков http и прочую работу. На этом работа MVC Framework завершается. Вместе с ним завершается статья с описанием механизма работы MVC Framework.

Progg it
Tags:
Hubs:
+14
Comments 8
Comments Comments 8

Articles