We put points in the MVC Framework. The mechanism of work, part two
This is the third article in a series of articles about the MVC Framework. In the first, I tried to answer the question “Why do we need the MVC Framework?”, And in the second I began the story of how it works. The story in the previous article implied a superficial description of the whole process of the MVC Framework without going into details. Details will follow later in the series of articles. This article will continue the story about the internal mechanism of the MVC Framework, which was interrupted on the description of Model Binding. We’ll start with him.
When the MVC Framework mechanism defines the controller class and the method of action in it that should participate in the formation of the response to the client request, the task is to pass the request parameters to the action. In the simplest case, the data transfer is carried out by comparing the request parameters with the method parameters. For example, if a user submits a form with data by filling in certain html elements, then the content values of these elements will be transferred to the action through the method parameter of the same name. Textarea data with the name attribute equal to address will be mapped to the action method parameter defined as string address .
The Model Binding mechanism deals with such a comparison, but its capabilities do not end with such a simple example. What to do when there are several tens of parameters on the form? We will not begin to create methods with two dozen parameters, just to get data from the form. Indeed, this is not necessary. Model Binding provides a wonderful opportunity to redefine the order of parameter matching and make initialization not in the form of “form parameter = method parameter”, but more complicated. For example, we can define a class or structure that will contain form data and in the method define only one parameter as an instance of this structure. Then defining the Model Binding mechanism for our complex type, we can initialize its properties with query parameters and call the action method, passing it an initialized object. As a result, numerous parameters on the form are transferred to the action method as an instance of the class with filled properties. Very comfortably.
But the MVC Framework developer doesn’t even need to do this, since the MVC Framework implements the DefaultModelBinder class , which does all the work of mapping query parameters to complex types. However, this does not stop you from defining your own Model Binding mechanism for certain types of parameters. This can be useful when, in addition to simply passing data from the request, you want to perform some other actions with an instance of a complex type.
The MVC Framework application has a standard ModelBinders property that contains a collection of user-defined parameter matching mechanisms. These mechanisms are an implementation of the IModelBinder interface , which contains only one BindModel methodwith the following definition:
public object BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext);
Using the controllerContext parameter passed by the MVC Framework mechanism, the developer can get access to all data of the request context, including parameters. The MVC Framework mechanism expects from the implementation of the IModelBinder interface an object that would determine the result of matching query parameters for a specific complex type to which the attribute is applied. Registration of its Model Binding mechanism is performed in global.asax in the Application_Start method as follows:
ModelBinders.Binders.Add (typeof (UserData), new UserDataBinder ());
where, typeof (UserData)- an indication of which complex type the matching mechanism is created for, new UserDataBinder () - an instance of the class that implements IModelBinder.
Note. In order to use these mechanisms not globally, but only locally, once, the developer, instead of registering the global Model Binding mechanism, can mark the required action parameter with the ModelBinder attribute, which contains the parameter defining the type of mechanism. How this is done is shown below:
public ActionResult Update ([ModelBinder (typeof (UserDataBinder))] UserData userData);
When the MVC Framework calls an action method, then for each parameter of a complex type, it looks for the Model Binding mechanism in the ModelBinders collection and calls it, if any. After that, the user-defined implementation of parameter mapping forms an object that is cast to the type of parameter and passed when the action is called. In the case when there is no user implementation for the complex type, the default parameter matching mechanism comes into play, which is implemented through DefaultModelBinder.
The developer can even more flexibly configure the execution of parameter matching using the BindAttribute attribute , which allows you to define several matching rules:
The operation of this attribute will be discussed in more detail in the following articles.
After all parameters are mapped, the ActionInvoker mechanism calls an action method that executes the logic of the action and, according to the rules of the MVC Framework, must return the result in the form of an ActionResult or its derivatives.
So, the action was called and returned the result in the form of an ActionResult or its derivatives. In general, the MVC Framework mechanism contains a number of such derivatives of the ActionResult class : ViewResult, JsonResult, FileResult, RedirectResult, RedirectToRouteResult, ContentResult, EmptyResult . Already by name you can determine the purpose of each of them. Each of these types of action result reflects the result that will be returned to the client in response to the request. It is important to note that the action is not involved in writing the result to the stream, forming markup, or other actions to send the result. All actions of the MVC Framework return data in the form of a specific ActionResult mechanism, which in turn does everything necessary so that the client receives the data in the desired form. This is called the execution of the result.
More details about the operation of ActionResult and the purpose of all its derivatives will be covered in subsequent articles.
The most powerful tool of the MVC Framework is that the developer can define his own version of the ActionResult implementation to form his own result in response to a client’s request. So, ActionResult, which returns an RSS feed, can be implemented very easily.
Having received the result in the form of ActionResult from the action, the MVC Framework mechanism (represented by ActionInvoker) calls the ExecuteResult method, which does all the work of forming markup, formatting data, creating http headers and other work. This completes the work of the MVC Framework. An article describing the mechanism of operation of the MVC Framework concludes with it.
Model binding
When the MVC Framework mechanism defines the controller class and the method of action in it that should participate in the formation of the response to the client request, the task is to pass the request parameters to the action. In the simplest case, the data transfer is carried out by comparing the request parameters with the method parameters. For example, if a user submits a form with data by filling in certain html elements, then the content values of these elements will be transferred to the action through the method parameter of the same name. Textarea data with the name attribute equal to address will be mapped to the action method parameter defined as string address .
The Model Binding mechanism deals with such a comparison, but its capabilities do not end with such a simple example. What to do when there are several tens of parameters on the form? We will not begin to create methods with two dozen parameters, just to get data from the form. Indeed, this is not necessary. Model Binding provides a wonderful opportunity to redefine the order of parameter matching and make initialization not in the form of “form parameter = method parameter”, but more complicated. For example, we can define a class or structure that will contain form data and in the method define only one parameter as an instance of this structure. Then defining the Model Binding mechanism for our complex type, we can initialize its properties with query parameters and call the action method, passing it an initialized object. As a result, numerous parameters on the form are transferred to the action method as an instance of the class with filled properties. Very comfortably.
But the MVC Framework developer doesn’t even need to do this, since the MVC Framework implements the DefaultModelBinder class , which does all the work of mapping query parameters to complex types. However, this does not stop you from defining your own Model Binding mechanism for certain types of parameters. This can be useful when, in addition to simply passing data from the request, you want to perform some other actions with an instance of a complex type.
The MVC Framework application has a standard ModelBinders property that contains a collection of user-defined parameter matching mechanisms. These mechanisms are an implementation of the IModelBinder interface , which contains only one BindModel methodwith the following definition:
public object BindModel (ControllerContext controllerContext, ModelBindingContext bindingContext);
Using the controllerContext parameter passed by the MVC Framework mechanism, the developer can get access to all data of the request context, including parameters. The MVC Framework mechanism expects from the implementation of the IModelBinder interface an object that would determine the result of matching query parameters for a specific complex type to which the attribute is applied. Registration of its Model Binding mechanism is performed in global.asax in the Application_Start method as follows:
ModelBinders.Binders.Add (typeof (UserData), new UserDataBinder ());
where, typeof (UserData)- an indication of which complex type the matching mechanism is created for, new UserDataBinder () - an instance of the class that implements IModelBinder.
Note. In order to use these mechanisms not globally, but only locally, once, the developer, instead of registering the global Model Binding mechanism, can mark the required action parameter with the ModelBinder attribute, which contains the parameter defining the type of mechanism. How this is done is shown below:
public ActionResult Update ([ModelBinder (typeof (UserDataBinder))] UserData userData);
When the MVC Framework calls an action method, then for each parameter of a complex type, it looks for the Model Binding mechanism in the ModelBinders collection and calls it, if any. After that, the user-defined implementation of parameter mapping forms an object that is cast to the type of parameter and passed when the action is called. In the case when there is no user implementation for the complex type, the default parameter matching mechanism comes into play, which is implemented through DefaultModelBinder.
The developer can even more flexibly configure the execution of parameter matching using the BindAttribute attribute , which allows you to define several matching rules:
- prefix used in markup for default matching;
- white and black lists of parameter names.
The operation of this attribute will be discussed in more detail in the following articles.
After all parameters are mapped, the ActionInvoker mechanism calls an action method that executes the logic of the action and, according to the rules of the MVC Framework, must return the result in the form of an ActionResult or its derivatives.
Result Execution and ActionResult
So, the action was called and returned the result in the form of an ActionResult or its derivatives. In general, the MVC Framework mechanism contains a number of such derivatives of the ActionResult class : ViewResult, JsonResult, FileResult, RedirectResult, RedirectToRouteResult, ContentResult, EmptyResult . Already by name you can determine the purpose of each of them. Each of these types of action result reflects the result that will be returned to the client in response to the request. It is important to note that the action is not involved in writing the result to the stream, forming markup, or other actions to send the result. All actions of the MVC Framework return data in the form of a specific ActionResult mechanism, which in turn does everything necessary so that the client receives the data in the desired form. This is called the execution of the result.
More details about the operation of ActionResult and the purpose of all its derivatives will be covered in subsequent articles.
The most powerful tool of the MVC Framework is that the developer can define his own version of the ActionResult implementation to form his own result in response to a client’s request. So, ActionResult, which returns an RSS feed, can be implemented very easily.
Having received the result in the form of ActionResult from the action, the MVC Framework mechanism (represented by ActionInvoker) calls the ExecuteResult method, which does all the work of forming markup, formatting data, creating http headers and other work. This completes the work of the MVC Framework. An article describing the mechanism of operation of the MVC Framework concludes with it.