ASP.NET Core - MVC Request Life Cycle

Earlier, I wrote a brief overview of ASP.NET MVC Request Life Cycle here. In this article, we will discuss the same in ASP.NET Core.

While in ASP.NET MVC, a request is handled using HttpModules & HttpHandlers. The ASP.NET Core MVC request lifecycle involves middleware. So what is middleware? Think of middleware as a series of blocks that are executed when a request is processed. If before proceeding you want to know more about middleware, this link from Microsoft is a good starting point.

When the application is started, it hits the Main method in program.cs.

ASP.NET Core - The MVC Request Life Cycle
This method then calls the ConfigureServices method in startup.cs. This is where all the required services in the application are added. Notice the AddMvc line.
 
ASP.NET Core - The MVC Request Life Cycle

The ConfigureServices method then calls the configure method which calls the UseMvc middleware. This middleware then calls the routing middleware (UseRouter).

ASP.NET Core - The MVC Request Life Cycle

We can see that a default route is created in this method. The routes specified in this UseMvc method are stored in a Routedata object.

When a request comes in, first, the attribute routes are evaluated and then conventional routes. Attribute routing is handled by MVCAttributeRouteHandler. Attribute routes are evaluated in parallel while in conventional routing the sequence of routing specified matters.

The MVCRouteHandler calls the RouteAsync method. This method calls the SelectCandidates method which selects all possible methods and checks if the entered URL has a match in the route data. This is simply a name comparison. Then the SelectBestCandidates method is called which narrows down the choice based on action constraints like HttpPost and HttpGet. If a match is found then the particular controller and action method are selected.

The thing to note here is in non-core framework, the MVC Controllers are inherited from the Controller class whereas the API controllers are inherited from the ApiController class. With the Core framework, both types of controllers inherit from the same controller class.

The MVC RouteHandler decides the controller that needs to be invoked. The controller Factory class and the controller activator class create an instance of the controller and an action method is selected.

Before the controller is created, authorization filters are called. If the authorization is successful, then the controller is created. Once the controller is created and the action method selected, model binding takes place. This is responsible for populating the action method parameters using querystrings, form data, route data, etc.

After the model binding takes place, the OnActionExecuting filter is executed. First, the action method is executed. Then, the OnActionExecuted filter is executed. Action result is now generated. Remember that in MVC, there is a difference between action result generation and the actual rendering of the action result.

After this, OnResultExecuting filters are executed next and the action result is invoked. After this, the OnResultExecuted filter is executed. This is the last stage where an action result can be modified.
Since in ASP.NET core, the MVC lifecycle and Web API lifecycle are now integrated into one, content negotiation also takes place when creating an ActionResult.

After this action, the results like JsonResult, ViewResult, etc. are rendered, depending upon the action result that needs to be created.

The diagram below outlines the steps that we have discussed above.

ASP.NET Core - The MVC Request Life Cycle

If you are interested in delving further into this topic, the ASP.NET Core: The MVC Request Life Cycle course on Pluralsight by Alex Wolf is an excellent place to begin.

This article was originally published on my website taagung.