We put points in the MVC Framework. The mechanism of work, part one
In this and the next article, points are put in the answer to the question “How does the MVC Framework work?”
This is a continuation of the ASP.NET MVC Framework series of notes. The beginning was laid in a previous article , which raised the question of the need to switch to the MVC Framework. After comments appeared, it became obvious that the article was not written in vain, since a certain part of readers does not represent the difference between the two approaches: the classic ASP.NET and the MVC Framework. I hope that the questions raised in the first chapter made someone think.
This time we will talk about how the MVC Framework mechanism is arranged from the inside. Habrahabr already had a publication about this, but I will try to give a more detailed description and touch on mechanisms that were not mentioned in that article.
The ASP.NET routing mechanism is an important element of the MVC Framework. In the standard version, when the first request to the application arrives and the application is created, the routes defined by the developer are initialized in the Global.asax file using the Application_Start method .
Strictly speaking, query processing is handled by mechanisms that cannot be called part of the MVC Framework. Request processing assigned to UrlRoutingModuleIs a class that implements IHttpModule, defined in MVC Framework projects as a module that processes http requests. UrlRoutingModule, as a routing mechanism, is a standard part of ASP.NET and it is quite possible to use it outside the MVC Framework. If we consider UrlRoutingModule in the context of the MVC Framework, then its task is to create and initialize an object of type RequestContext , which in turn is used by the MVC mechanism.
In a simplified form, the request processing scheme is the following sequence of actions:
A controller factory is a mechanism whose task is to instantiate controller classes based on the transmitted information in the form of a controller name and an object of type RequestContext. The controller factory must implement the IControllerFactory interface . But in the general case, there is no need to define your controller factory, since in the MVC Framework there is a class DefaultFactoryController , which is the default controller factory.
The MVC Framework uses the controller factory's CreateController method to obtain an object of type IController . At this stage, the creation of the controller is completed and the Execute method is called , to which the parameter in the form of RequestContext is passed.
At the stage of the controller factory, there is a great opportunity to expand the functionality, which shows how extensible the MVC Framework is. You can define your own controller factory class by inheriting it from the DefaultFactoryController class. Then, overriding the GetControllerInstance method in your class, you can define your own logic for creating controllers in it. To register your controller factory, you can add the following code to the Application_Start method of the Global.asax file:
ControllerBuilder.Current.SetControllerFactory (new ControllerFactory ());
Why might you need to create your own controller factory? One of the most common options is to implement an IoC / DI mechanism for instantiating controllers using a DI container, for exampleUnity Application Blocks .
So, the controller is created and the Execute method is called for it. What's next?
And then the ActionInvoker mechanism comes into play , the purpose of which is to find out which method of the controller class should be performed in response to a user request. ActionInvoker is a property of the Controller class, which is usually derived from all controllers in the MVC Framework. ActionInvoker is an object of the ControllerActionInvoker class . Its important part is the InvokeAction method , which searches for the required method of the controller class, calls it and executes the result.
To work, the InvokeAction method accepts the context parameters of the controller and the name of the action to be found. Although searching in a method class by name is trivial, there are several important points that affect search results. The following four groups of attributes affect the process of executing an action and its result:
According to the architecture of the MVC Framework, you can replace each part of it with your own. ActionInvoker, as well as all the attributes described above, did not bypass this principle. You can define your ActionInvoker, for this you just need to implement the class inheriting from the ControllerActionInvoker class and override the InvokeAction method. Such an override will allow you to create your own mechanism for searching for a method, its execution, and processing the result. To register your version of ActionInvoker, just assign its instance to the controller property:
public AccountController ()
: this (null, null) {
ActionInvoker = new FastControllerActionInvoker ();
}
After ActionInvoker has determined which method to call, the Model Binding mechanism comes into play , which is designed to match client request parameters with action method parameters.
Due to the fact that the material is too large, the Model Binding mechanism, as well as the completion of the description of the mechanism and all these attributes, will be presented in the following articles.
This is a continuation of the ASP.NET MVC Framework series of notes. The beginning was laid in a previous article , which raised the question of the need to switch to the MVC Framework. After comments appeared, it became obvious that the article was not written in vain, since a certain part of readers does not represent the difference between the two approaches: the classic ASP.NET and the MVC Framework. I hope that the questions raised in the first chapter made someone think.
This time we will talk about how the MVC Framework mechanism is arranged from the inside. Habrahabr already had a publication about this, but I will try to give a more detailed description and touch on mechanisms that were not mentioned in that article.
Request Processing and Routing
The ASP.NET routing mechanism is an important element of the MVC Framework. In the standard version, when the first request to the application arrives and the application is created, the routes defined by the developer are initialized in the Global.asax file using the Application_Start method .
Strictly speaking, query processing is handled by mechanisms that cannot be called part of the MVC Framework. Request processing assigned to UrlRoutingModuleIs a class that implements IHttpModule, defined in MVC Framework projects as a module that processes http requests. UrlRoutingModule, as a routing mechanism, is a standard part of ASP.NET and it is quite possible to use it outside the MVC Framework. If we consider UrlRoutingModule in the context of the MVC Framework, then its task is to create and initialize an object of type RequestContext , which in turn is used by the MVC mechanism.
In a simplified form, the request processing scheme is the following sequence of actions:
- UrlRoutingModule processes the request and on its basis selects the first suitable route from the route collection specified by the developer;
- UrlRoutingModule, based on the route represented by an object of type Route , creates an object of type RequestContext. RequestContext contains data about the context of the request execution and data regarding the current route;
- in the MVC Framework, a route handler is assigned to each route by default in the form of an MVCRouteHandler object , which generally creates and returns an instance of the MVCHandler class , to which the RequestContext object created earlier is transferred;
- MVCHandler takes the last step, it creates a controller factory and with it receives the MVC Framework controller object necessary to continue processing the request.
Controller factory
A controller factory is a mechanism whose task is to instantiate controller classes based on the transmitted information in the form of a controller name and an object of type RequestContext. The controller factory must implement the IControllerFactory interface . But in the general case, there is no need to define your controller factory, since in the MVC Framework there is a class DefaultFactoryController , which is the default controller factory.
The MVC Framework uses the controller factory's CreateController method to obtain an object of type IController . At this stage, the creation of the controller is completed and the Execute method is called , to which the parameter in the form of RequestContext is passed.
At the stage of the controller factory, there is a great opportunity to expand the functionality, which shows how extensible the MVC Framework is. You can define your own controller factory class by inheriting it from the DefaultFactoryController class. Then, overriding the GetControllerInstance method in your class, you can define your own logic for creating controllers in it. To register your controller factory, you can add the following code to the Application_Start method of the Global.asax file:
ControllerBuilder.Current.SetControllerFactory (new ControllerFactory ());
Why might you need to create your own controller factory? One of the most common options is to implement an IoC / DI mechanism for instantiating controllers using a DI container, for exampleUnity Application Blocks .
So, the controller is created and the Execute method is called for it. What's next?
Actioninvoker
And then the ActionInvoker mechanism comes into play , the purpose of which is to find out which method of the controller class should be performed in response to a user request. ActionInvoker is a property of the Controller class, which is usually derived from all controllers in the MVC Framework. ActionInvoker is an object of the ControllerActionInvoker class . Its important part is the InvokeAction method , which searches for the required method of the controller class, calls it and executes the result.
To work, the InvokeAction method accepts the context parameters of the controller and the name of the action to be found. Although searching in a method class by name is trivial, there are several important points that affect search results. The following four groups of attributes affect the process of executing an action and its result:
- attributes derived from ActionMethodSelectorAttribute can affect whether or not the method to execute is selected depending on the context of the request . There are two such standard attributes in the MVC Framework: AcceptVerbsAttribute and NonActionAttribute ;
- attributes derived from ActionNameSelectorAttribute can affect whether or not the method to be executed is selected depending on the name of the action to be performed. There is one such attribute in the MVC Framework - ActionNameAttribute ;
- Attributes derived from FilterAttribute are the so-called filter mechanisms that allow you to more flexibly control the process of executing an action. These filters are designed to either limit the execution of an action for some reason, or handle the exceptions that occur during execution. The standard implementations of these filters are the attributes AuthorizeAttribute, HandleErrorAttibute, ValidateAntiForgeryTokenAttribute and ValidateInputAttribute ;
- another attribute ActionFilterAttribute , derived from FilterAttribute, allows you to create a mechanism that will be called in four key places of the action: before execution, after execution, before execution of the result and after execution of the result. The implementation of this attribute will allow you to more flexibly influence the process of execution of an action and result, track it and manage it. The MVC Framework has one attribute derived from ActionFilterAttribute - this is OutputCacheAttribute .
According to the architecture of the MVC Framework, you can replace each part of it with your own. ActionInvoker, as well as all the attributes described above, did not bypass this principle. You can define your ActionInvoker, for this you just need to implement the class inheriting from the ControllerActionInvoker class and override the InvokeAction method. Such an override will allow you to create your own mechanism for searching for a method, its execution, and processing the result. To register your version of ActionInvoker, just assign its instance to the controller property:
public AccountController ()
: this (null, null) {
ActionInvoker = new FastControllerActionInvoker ();
}
After ActionInvoker has determined which method to call, the Model Binding mechanism comes into play , which is designed to match client request parameters with action method parameters.
Due to the fact that the material is too large, the Model Binding mechanism, as well as the completion of the description of the mechanism and all these attributes, will be presented in the following articles.