Inside ASP.NET MVC: Route to MvcHandler
In my previous post I promised to start with exploration of MvcHanlder
as entry point of ASP.NET MVC application. MvcHandler
plays the major role in MVC infrastructure, but as I fugured out - the whole story does not begin there. The story is actually begins inside ASP.NET framework.
ASP.NET framework
ASP.NET framework is heart of ASP.NET MVC application. Basically, ASP.NET is a request processing engine. It takes incoming request as input and sends it through internal pipeline till the end point. The architecture allows extensibility, you could plug either into pipeline (modules) or end points (handlers). Interesting fact that ASP.NET designed to be decoupled from actual request source. So, the source of request could be any application - IIS, Cassini or any custom one.
We could imagine that each request pass through the set of filters (internal pipeline) lands up on request handler (end point), request handler creates a response object and sent it back. There are a lot of hidden details of dealing with managed/unmanaged code that you could find in this brilliant article by Rick Strahl.
For us it is important to understand two basic abstractions, HttpModules and HttpHandlers.
HttpModules and HttpHandlers
From the developers point of view the difference between those are: one implements IHttpModule
interface another implements IHttpHandler
interface.
Module participates in the request processing of every request in order to change or add to it in some way.
Handler is responsible for handling the request and producing the response for specific content types.
ASP.NET MVC is HttpHandler.
There a bunch of default HttpModules and HttpHandlers in your IIS configuration. Just take a look here - %WINDOWS%\Microsoft.NET\Framework\v4.0.30319\Config\web.config.
But if you look closer you won’t notice any mention of System.Web.Mvc.MvcHanlder
. Hey. what’s wrong? How the runtime actually knows that MvcHanler
have to be called to handle our request? That was absolutely unclear to me at very beginning.
From request to handler
I opened WebRuntime.sln and found all references to MvcHandler
. It is only one place there, in the MvcRouteHandler
(MvcRouteHandler.cs) class. MvcRouteHandler implements IRouteHandler
interface, with one single method GetHttpHandler
. I put the breakpoint there and started application for debug.
As application got started I halted on breakpoint with such call stack:
Let’s try to read and decrypt it.
It begins with WebDev.WebHost40.dll
(Cassini Web Server) that receives request and System.Web.HttpRuntime.ProcessRequest
. Here is ASP.NET framework start to work:
-
ProcessRequestInternal method called. This is the primary method of whole pipeline. First, it initialize the
HttpContext
object.
-
Next it get
HttpApplication
instance, initialize it and calls either BeginProcessRequest
for IHttpAsyncHandler
or ProcessReques
for IHttpHandler
.
-
If I go to
global.asax.cs
of our application it is clear that System.Web.HttpApplication
implementation is inherited and System.Web.HttpApplication
is a usual IHttpAsyncHandler
. So, async BeginProcessRequest
starts.
- In
BeginProcessRequest
there is a cycle that iterates all modules and execute each of it. Reflector code looks messy, but the point is clear
- And finally, the control goes to UrlRoutingModule that calls our factory method for
MvcHandler
. Aha!
UrlRouting module
UrlRouting is an HttpModule, registered in global web.config:
The goal of this module is basically matching incoming request by URL with pre-defined Route configuration and return corresponding handler for this request. In PostResolveRequestCache
method it gets the RouteHandler and asks for corresponding HttpHanlder.
Wow, I didn’t know that!.. UrlRouting plays a major role inside the MVC infrastructure. But there the Routes are initialized and how MvcRouteHandler
is associated with request?
Back to roots - Application_Start() method
I should actually start from here, Application_Start()
is entry point of application. By my journey turn to be just other way around.
Inside the RegisterRoutes
we register route by giving: route name and constraints.
The MapRoute
is actually extension method in RouteCollectionExtensions.cs.
Now, you can see how the route with particular URL is being register and associated with MvcRouteHandler
.
Putting it all together
Now it is time to get deep breath and finally understand the route of HTTP request to MvcHttpHandler. Here we go:
- ASP.NET framework starting to process incoming request in
ProcessRequest
method, but interesting stuff going in ProcessRequestInternal
ProcessRequestInternal
calls GetApplicationInstance
method that get application instance and calls it Application_Init()
Application_Init()
registers routes that map URL (like “home/index”) with MvcRouteHandler
instance
- ASP.NET framework starts to iterate modules for incoming request and found
UrlRouting
module
UrlRouting
module matches incoming request URL with registered collections of Routes
- For found matched Route it gets corresponding route handler (MvcRouteHandler)
MvcHandler
is being returned by GetHttpHandler of MvcRouteHandler
That’s the routing that is being executed each time you put URL and hit your browser button.
What’s next?
I hope next time we indeed look closer to MvcHandler
:).
Previous: Inside ASP.NET MVC: Part 2: Setting up project for hacking
Next: Inside ASP.NET MVC: All begins here - MvcHanlder
In my previous post I promised to start with exploration of MvcHanlder
as entry point of ASP.NET MVC application. MvcHandler
plays the major role in MVC infrastructure, but as I fugured out - the whole story does not begin there. The story is actually begins inside ASP.NET framework.
ASP.NET framework
ASP.NET framework is heart of ASP.NET MVC application. Basically, ASP.NET is a request processing engine. It takes incoming request as input and sends it through internal pipeline till the end point. The architecture allows extensibility, you could plug either into pipeline (modules) or end points (handlers). Interesting fact that ASP.NET designed to be decoupled from actual request source. So, the source of request could be any application - IIS, Cassini or any custom one.
We could imagine that each request pass through the set of filters (internal pipeline) lands up on request handler (end point), request handler creates a response object and sent it back. There are a lot of hidden details of dealing with managed/unmanaged code that you could find in this brilliant article by Rick Strahl.
For us it is important to understand two basic abstractions, HttpModules and HttpHandlers.
HttpModules and HttpHandlers
From the developers point of view the difference between those are: one implements IHttpModule
interface another implements IHttpHandler
interface.
Module participates in the request processing of every request in order to change or add to it in some way.
Handler is responsible for handling the request and producing the response for specific content types.
ASP.NET MVC is HttpHandler.
There a bunch of default HttpModules and HttpHandlers in your IIS configuration. Just take a look here - %WINDOWS%\Microsoft.NET\Framework\v4.0.30319\Config\web.config.
But if you look closer you won’t notice any mention of System.Web.Mvc.MvcHanlder
. Hey. what’s wrong? How the runtime actually knows that MvcHanler
have to be called to handle our request? That was absolutely unclear to me at very beginning.
From request to handler
I opened WebRuntime.sln and found all references to MvcHandler
. It is only one place there, in the MvcRouteHandler
(MvcRouteHandler.cs) class. MvcRouteHandler implements IRouteHandler
interface, with one single method GetHttpHandler
. I put the breakpoint there and started application for debug.
As application got started I halted on breakpoint with such call stack:
Let’s try to read and decrypt it.
It begins with WebDev.WebHost40.dll
(Cassini Web Server) that receives request and System.Web.HttpRuntime.ProcessRequest
. Here is ASP.NET framework start to work:
-
ProcessRequestInternal method called. This is the primary method of whole pipeline. First, it initialize the
HttpContext
object. -
Next it get
HttpApplication
instance, initialize it and calls eitherBeginProcessRequest
forIHttpAsyncHandler
orProcessReques
forIHttpHandler
. -
If I go to
global.asax.cs
of our application it is clear thatSystem.Web.HttpApplication
implementation is inherited andSystem.Web.HttpApplication
is a usualIHttpAsyncHandler
. So, asyncBeginProcessRequest
starts. - In
BeginProcessRequest
there is a cycle that iterates all modules and execute each of it. Reflector code looks messy, but the point is clear - And finally, the control goes to UrlRoutingModule that calls our factory method for
MvcHandler
. Aha!
UrlRouting module
UrlRouting is an HttpModule, registered in global web.config:
The goal of this module is basically matching incoming request by URL with pre-defined Route configuration and return corresponding handler for this request. In PostResolveRequestCache
method it gets the RouteHandler and asks for corresponding HttpHanlder.
Wow, I didn’t know that!.. UrlRouting plays a major role inside the MVC infrastructure. But there the Routes are initialized and how MvcRouteHandler
is associated with request?
Back to roots - Application_Start() method
I should actually start from here, Application_Start()
is entry point of application. By my journey turn to be just other way around.
Inside the RegisterRoutes
we register route by giving: route name and constraints.
The MapRoute
is actually extension method in RouteCollectionExtensions.cs.
Now, you can see how the route with particular URL is being register and associated with MvcRouteHandler
.
Putting it all together
Now it is time to get deep breath and finally understand the route of HTTP request to MvcHttpHandler. Here we go:
- ASP.NET framework starting to process incoming request in
ProcessRequest
method, but interesting stuff going inProcessRequestInternal
ProcessRequestInternal
callsGetApplicationInstance
method that get application instance and calls itApplication_Init()
Application_Init()
registers routes that map URL (like “home/index”) withMvcRouteHandler
instance- ASP.NET framework starts to iterate modules for incoming request and found
UrlRouting
module UrlRouting
module matches incoming request URL with registered collections of Routes- For found matched Route it gets corresponding route handler (MvcRouteHandler)
MvcHandler
is being returned by GetHttpHandler of MvcRouteHandler
That’s the routing that is being executed each time you put URL and hit your browser button.
What’s next?
I hope next time we indeed look closer to MvcHandler
:).
Previous: Inside ASP.NET MVC: Part 2: Setting up project for hacking Next: Inside ASP.NET MVC: All begins here - MvcHanlder