In this and the next article points are put in response to the question “How does the MVC Framework work?”
This is a continuation of the cycle of notes about the ASP.NET MVC Framework. A start was made in the
previous article , which raised the question of the need to move to the MVC Framework. After the appearance of comments, it became obvious that the article was not written in vain, since a certain part of readers do not represent the meaning and difference of the two approaches: the classical ASP.NET and the MVC Framework. I hope that the questions raised by the first chapter made someone think.
This time it will be about how the MVC Framework is built from the inside. Habrahabr already had a
publication on this subject, but I will try to give a more detailed description and touch on the 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 arrives at the application and the application is created, the routes specified by the developer are initialized in the
Global.asax file using the
Application_Start method.
')
Strictly speaking, the processing of a request is handled by mechanisms that cannot be called an integral part of the MVC Framework. Request processing is assigned to
UrlRoutingModule - this is a class implementing 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 the 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, based on it, selects the first suitable route from the route collection defined by the developer;
- UrlRoutingModule, on the basis of a route represented by an object of type Route , creates an object of type RequestContext. RequestContext contains information about the context of the request and data relating to the current route;
- in the MVC Framework, each route is assigned a default route handler as an MVCRouteHandler object, which generally creates and returns an instance of the MVCHandler class, to which the RequestContext object created earlier is passed;
- MVCHandler takes the last step, it creates a controller factory and with it it gets the MVC Framework controller object that is necessary to continue processing the request.
Thus, a controller is created at the user's request. Consider the creation of controllers in more detail.
Controller Factory
A controller factory is a mechanism whose task is to instantiate controller classes based on the information transferred in the form of a controller name and an object of type RequestContext. The controller factory must implement the
IControllerFactory interface. But in general, there is no need to define your controller factory, since in the MVC Framework there exists the
DefaultFactoryController class, which is the default controller factory.
The MVC Framework uses the controller factory's
CreateController method to get an object of type
IController . At this stage, the creation of the controller is completed and its
Execute method is called, to which the parameter is passed in the form of a RequestContext.
At the controller factory stage, there is a remarkable possibility of expanding the functional, which shows how expandable the MVC Framework is. You can define your own controller factory class by inheriting it from the DefaultFactoryController class. Then, by redefining 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 you may need to create your own factory of controllers? One of the most common options is to implement an IoC / DI mechanism to instantiate controllers using a DI container, such as
Unity Application Blocks .
So, the controller is created and its Execute method is called. What's next?
ActionInvoker
And then the
ActionInvoker mechanism
comes in , the goal of which is to find out which controller class method needs to be executed 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 performs the search for the required method of the controller class, its call and the execution of the result.
For operation, the InvokeAction method accepts the parameters of the controller context 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 the search results. The following four attribute groups affect the process of executing an action and its result:
- Attributes derived from ActionMethodSelectorAttribute can affect whether or not a method is chosen to be executed 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 a method is chosen to be executed depending on the name of the action to be executed. In the MVC Framework, there is one such attribute - ActionNameAttribute ;
- Attributes derived from FilterAttribute are the so-called filter mechanisms that allow you to more flexibly control the process of performing an action. These filters are designed to either restrict the execution of an action for some reason, or handle the exceptions that occur during the execution. Standard implementations of these filters are the AuthorizeAttribute, HandleErrorAttibute, ValidateAntiForgeryTokenAttribute, and ValidateInputAttribute attributes;
- Another attribute, ActionFilterAttribute , derived from FilterAttribute, allows you to create a mechanism that will be called in four key execution points 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. In the MVC Framework, there is one attribute derived from the ActionFilterAttribute - this is OutputCacheAttribute .
If you read all this and did not understand anything, then wait a bit, in the following articles I will try to describe each of the attributes in more detail. In the meantime, let's continue to analyze how the ActionInvoker mechanism works.
According to the MVC Framework architecture, you can replace each part with its own. This principle did not bypass the side and ActionInvoker, as well as all the attributes described above. You can define your ActionInvoker, for this you just need to implement a class that inherits from the ControllerActionInvoker class and override the InvokeAction method. Such a redefinition will allow you to create your own mechanism for finding a method, its execution and processing the result. To register your ActionInvoker variant, it is enough to assign its instance to the controller property:
public AccountController ()
: this (null, null) {
ActionInvoker = new FastControllerActionInvoker ();
}After ActionInvoker has determined which method to invoke, the
Model Binding mechanism comes in, which is designed to match the parameters of the client request with the parameters of the action method.
Due to the fact that the material turns out to be too large, the Model Binding mechanism, as well as the completion of the description of the operation of the mechanism and all these attributes will be presented in the following articles.
