Alexander Beletsky's development blog

My profession is engineering

Inside ASP.NET MVC: All begins here - MvcHanlder

Last time we explored a way of HTTP request from the IIS up to MvcHanlder. Then UrlRouting module match URL we registered in Application_Start(), it gets corresponding IRouteHandler class and calls for GetHttpHandler method. In ASP.NET MVC URL IRouteHandler interface is implemented by MvcRouteHandler class which return MvcHanlder instance. The actual MVC story begins exactly in MvcHanlder internals.

Generic overview

We know that HttpHandlers are special objects that handles requests and produce a response. MvcHanlder produce nothing by itself. Instead, it uses ControllerBuilder object for creating Controller and call controller Execute method. It is Execute method responsibility to find corresponding action, call action and wrap action return result it HTTP response.

mvc handler declaration

As you can see, it implements 3 interfaces: IHttpHandler, IHttpAsyncHandler and IRequiresSessionState. The handler could operate in 2 modes: sync and async, depending on caller. ASP.NET frameworks ProcessRequestInternal method try to utilize asynchronous mode of work first.

The constructor of MvcHanlder receives RequestContext class, that is part of System.Web.Routing and contains information about HttpContext.

Synchronous and Asynchronous modes

Of course, the details of operation in synchronous and asynchronous modes are differ from each other, but main algorithm of work is exactly the same.. Let’s first see how it operates in sync mode.

Process the request

Due to IHttpHandler interface, MvcHanlder expected to support one property and one method:

mvc handler declaration

IsReusable is always false, meaning that for each request the runtime would create new instance of handler. ProcessRequest receives HttpContext and basically delegates call to internal ProcessRequest method.

mvc handler declaration

Notice to the first line.. HttpContext is being wrapped with HttpContextWrapper and casted to HttpContexBase. Rest of code never (mostly) using HttpContext directly, but through HttpContexBase. The HttpContexBase have been introduced to improve testability of ASP.NET applications, since HttpContext is unable to be mocked.

ControllerBuilder, ControllerFactory, Controller

Let’s see inside the ProcessRequest method to see how exactly the controller is being constructed and called.

mvc handler declaration

The call is wrapped with a little security handler, that would do perform the check for Trust settings, before calling internal action. Inside the action IController and IControllerFactory are being declared and initialized in ProcessRequestInit method.

mvc handler declaration

First, it puts MVC version information into HTTP response header, removes optional parameters from routes (one we mark with UrlParameter.Optional) and gets the name of controller from RequestContext. Remember, in global.asax we define URL pattern like “{controller}/{action}/{index}”, so in case of such URL products/search/122 the GetRequiredString will return “products”.

ControllerBuilder is a singleton and factory method that creates IControllerFactory instance.

ControllerFactory is responsible for creation of controller by given name.

The ProcessRequestInit gets the factory from ControllerBuilder, ask factory to create controller by the name from URL and returns results back to ProcessRequest.

Here we also could see good example of comments that lies.. “// Instantiate the controller and call Execute” - maybe sometime ago that was true, but not its false since Execute is not called here.

Execution

As soon as controller factory and controller are successfully created, ProcessRequest calls for controller Execute method. Now, it is controller responsibility to produce the output and we will see how it does that in next “Inside MVC” posts. Execution is wrapped inside try / finally block and finalize code will release the controller by calling ReleaseContoller method of factory.

Meanwhile in Asynchronous…

In async world the things are bit more complex. There are no one single method, but 2 instead. BeginProcessRequest and EndProcessRequest.

The request initialization and creation of factory and controller is exactly the same. The difference in execution, for async controller 2 delegates are being created,

mvc handler declaration

In fact, that than the request execution begins, beginDelegate is called that would call BeginExecute of the controller. At the end of request endDelegate called that would call EndExecute of controller.

What about tests?

That was a great surprise to me that MvcHandler is well unit tested. All aspects of its work are covered with corresponding tests.. I’ve heard a lot of developers complains like, “oh, it is so low-level code.. could not test it”. But MVC team, proof it is wrong. HttpContexBase could be easy mocked, so no excuse of not writing unit tests for modules/handlers. As I said in into, test code is really clean, following AAA principle’s, so I got a lot of pleasure of looking inside.

BTW, they are using Moq framework for mocking, that I personally like as well :).

Previous: Inside ASP.NET MVC: Route to MvcHandler Next: Inside ASP.NET MVC: ControllerBuilder class