📜 ⬆️ ⬇️

Request Processing in ASP.NET MVC

I will try to contribute to the development of a relatively untapped ASP.NET MVC framework and offer you a translation of the excerpt from the book " Pro ASP.NET MVC Framework " entitled "The Request Processing Pipeline".

***

Let's take a look at what happens in runtime mode when ASP.NET MVC processes an incoming request.
')
ASP.NET MVC query processing pipeline is comparable to the page life cycle in ASP.NET WebForms in that it displays the anatomy of the system. An understanding of this process is necessary to perform any non-standard tasks. Unlike the traditional page life cycle in ASP.NET, the request processing pipeline in MVC is very flexible — you can change any part of it as you like, and even redistribute or replace some components. Although you usually do not have to expand or change the pipeline, you can do it at any time, because extensibility is at the core of ASP.NET MVC.


The figure shows the query processing pipeline. The central axis is a standard pipeline (for requests that render a view); branches are the main points of expansion. To simplify the scheme does not contain absolutely all the stages and points of expansion. The most significant omission is filters that can be embedded before or after the execution of action methods, or before or after the execution of action results.

image

STEP 1: IIS


Internet Information Services (IIS), a web server from Microsoft, starts up first. When an HTTP request arrives, before the ASP.NET comes into play, the Windows kernel's HTTP.SYS driver analyzes the URL / port number / IP address combination, matches them and redirects to the registered application (which can be either an IIS website or virtual directory inside the IIS website).

Since ASP.NET MVC applications are based on ASP.NET, you need to enable ASP.NET for the application pool (each IIS application is associated with an application pool). ASP.NET can be enabled in two managed pipeline modes (managed pipeline modes):

• In ISAPI mode (classic mode), ASP.NET is activated using the ISAPI extension (aspnet_isapi.dll) associated with certain file extensions from a URL address (for example, .aspx, .ashx, .mvc). In IIS 6, you can use wildcards, and then aspnet_isapi.dll will process all requests despite the file extension.

• In integrated mode (supported only in IIS 7+), .NET is the native part of the query processing pipeline, so you do not need to use the ISAPI extension associated with file extensions. This is what makes it easy to use routing with “beautiful” URL addresses (without file extensions).

In any case, as soon as the ASP.NET system accepts an incoming request, it notifies all registered HTTP modules that a new request has arrived. (The HTTP module is a .NET class that implements the IHttpModule interface, which can be embedded in the request processing pipeline). One particularly important HTTP module, registered by default in all ASP.NET MVC applications, is UrlRoutingModule. This module is the starting point of the entire routing system (core routing system). For IIS 6, the UrlRoutingModule module is registered in the web.config file.

For IIS 7, you can use the Modules GUI (to do this, open the Internet Information Services (IIS) Manager from Administrative Tools, select the website and double-click Modules).

STAGE 2: ROUTING (CORE ROUTING)


When the UrlRoutingModule module enters into the processing of a request, it starts the System.Web.Routing routing system. The routing task is to recognize and analyze the incoming URL and fill in the request context that subsequent components can use (for example, ASP.NET MVC uses it to transfer control to the appropriate MVC controller and populate the action method parameters).

The diagram shows that the routing system first checks whether the incoming URL matches the file on disk. If yes, then the routing system ends its work and IIS continues processing the request. For static files (for example, .gif, .jpeg, .png, .css, or .js), this means that IIS will process them in a standard way (because they exist on disk), which is very efficient. Similarly, traditional ASP.NET WebForms (.aspx) pages will be processed in the usual way.

However, if the incoming URL does not correspond to the file on disk (for example, requests to MVC controllers that are .NET classes, not files), then the routing system examines the current configuration in order to determine how to handle the incoming URL.

ROUTING TABLE

The routing table is stored in the System.Web.Routing.RouteTable.Routes static collection. Each entry in the collection is a template for valid URLs. The template can optionally include placeholders (for example, / blog / {year} / {entry}) and constraints that limit the range of acceptable values ​​for each of the parameters. Each entry points to a route handler (route handler) - an object that implements the IRouteHandler interface that accepts and processes the request. In order to populate the RouteTable.Routes collection, add the appropriate code to the RegisterRoutes () method of the Global.asax.cs file.

To search for a matching HTTP request to a specific route from RouteTable.Routes, the routing system starts scanning the RouteTable.Routes collection from top to bottom and selects the first route found that matches the incoming request. Having found it, the routing system transfers control to the route handler, providing it with the context of the request, describing the selected route and all URL parameters.

STAGE 3: CONTROLLERS AND ACTIONS (CONTROLLERS AND ACTIONS)


At this point, the routing system selected a route from the RouteTable.Routes collection and analyzed the URL parameters. All this information is placed in the context of the request. So where are the controllers and actions on the scene?

SEARCH AND LAUNCH OF CONTROLLERS

For ASP.NET MVC applications, most routes from RouteTable.Routes correspond to one handler — the MvcRouteHandler handler; this is the standard handler built into ASP.NET MVC. MvcRouteHandler knows how to call the appropriate controller using the request context.

As can be seen in the diagram, he does this using the controller factory. By default, it uses the incredibly original factory named DefaultControllerFactory, which uses a specific controller naming convention to select the correct controller for the incoming request.

However, if you replace the DefaultControllerFactory's built-in factory with some other implementation of the IControllerFactory interface or a successor of the DefaultControllerFactory class, then you must change this logic.

WHAT SHOULD MAKE CONTROLLERS

The minimum requirement for a controller class is that it must implement the IController interface:

public interface IController
{
void Execute (RequestContext requestContext);
}

As you can see, this is a very simple interface! It does not define anything, except that the controller has to do something in the Execute () method. Notice that the requestContext parameter stores complete information about the request context generated by the routing system, including URL parameters, and also provides access to Request and Response objects.

WHAT CONTROLLERS DO USUALLY

Most often, there is no need to implement IController directly - you can inherit controllers from the System.Web.Mvc.Controller class. This is the standard ASP.NET MVC base controller, which adds the necessary infrastructure for processing requests. Most importantly, it introduces action methods into the system. This means that all public controller methods are reachable via URLs (such methods are called “action methods”) and, in addition, this means that you do not need to independently implement the Execute () method.

Although action methods can output the result directly in the HTTP response, this is not recommended. For reasons of convenience of testing and reusing code in action methods, it is better to return the result of actions (action result) (an object inherited from ActionResult), which describes the result of performing an action. For example, if you want to render a view, return the ViewResult. Or, to redirect an HTTP request to another action method, return RedirectToRouteResult. ASP.NET MVC takes care of executing the result at the right moment in the query processing pipeline.

In addition, there is a very flexible system filter. These are .NET attributes (for example, [Authorize]), which you can use to label controller classes or action methods by embedding any logic before or after performing action methods, or before or after running the results of actions. There are several built-in filters, such as exception filters and authorization filters. Filters can be applied in so many different places that they have no place on the diagram!

Controllers and actions (and their associated capabilities) are the core concepts in ASP.NET MVC.

STAGE 4: RESULTS ACTIONS AND REPRESENTATIONS (ACTION RESULTS AND VIEWS)


Ok, yes, quite a lot has already happened! Let's repeat:

• The routing system matched the incoming URL with a specific route and prepared an object containing the request context. The route selected from RouteTable.Routes has designated the MvcRouteHandler handler for processing the request.

• MvcRouteHandler used the request context and the controller factory to select and call the appropriate controller.

• The controller called one of its action methods.

• The action method returned an ActionResult object.
At this point, ASP.NET MVC executes the result of the ActionResult.

RENDERING REPRESENTATIONS

Let's pay special attention to one special class inherited from ActionResult - ViewResult. This class is able to find and render the corresponding view template, passing to it something in the ViewData collection, formed in the action method. This is what is called the “view engine” (a .NET class that implements the IViewEngine interface).

The standard engine is WebFormViewEngine. Its presentation templates are WebForms pages (.aspx) (that is, server pages used in traditional ASP.NET WebForms technology). WebForms pages have their own processing pipeline, starting with an ASPX / ASCX compilation on the fly and going through a series of events called the page life cycle. Unlike traditional ASP.NET, in ASP.NET MVC, these pages should be as simple as possible, since, according to MVC principles, views can only be responsible for generating HTML code. This means that you do not need to understand in detail the life cycle of WebForms pages. With the observance of the principles of separation of roles come simplicity and ease of maintenance code.

***

From myself I would like to add that the article " 13 ASP.NET MVC extensibility points you have to know " can be useful directly on this topic.

Source: https://habr.com/ru/post/62694/


All Articles