Apr 02

The MVC framework: invoking actions asynchronously I

Posted in ASP.NET MVC      Comments Off on The MVC framework: invoking actions asynchronously I

As we’ll see, the MVC futures assembly adds several classes which help you in executing asynchronous actions. In this post, we’ll take a quick look at the infrastructure code needed to start adding asynchronous actions to your controllers. As you’ll that it would be good to make a small incursion into the internals that support asynchronous requests in the MVC futures assembly. If ysee (when we’re done with this series), the futures assembly gives you several options to perform an action asynchronously. Before showing some code, I believe ou take a look at the MVC futures source code, you’ll see that it has several classes that start with or contain the Async word. Those classes are responsible for supporting the features we’ll be seeing in this and in the next posts.

Ok, nothing better than go back to the basics…as you recall, the routing module is really important and introduces the hooking point from where the MVC framework does its work. By default, when you register a route you end up using a helper method that associates a route with an instance of type MvcRouteHandler. As we’ve seen in the past, the only role of this route handler is to return the IHttpHandler that will process the request. Whenever you want to use asynchronous actions in your MVC app, you’ll need to associate a route with a different route handler: in this case, you’re interesting in using the MvcAsyncRouteHandler.

If you want,you can pass a reference to this route handler when you create a new Route object (I call this the manual – but more explicit! – approach). However,you’ll probably prefer the quickest option which consists in using the RouteCollection extension methods defined in the static AsyncRouteCollectionExtensions class. As you might expect, you’ll find several overloads which let you set several of the properties of the Route you’re creating.

The MvcAsyncRouteHandler is really similar to the existing MvcRouteHandler. However, in this case, it will return an instance of type MvcAsyncHandler that is responsible for handling the current request. This is an asynchronous handler (ie, it implements the IHttpAsyncHandler) and it also extends the MvcHandler class by adding a new property (SynchronizationContext) used internally for context propagation/synchronization (by default, it ends up using the default ASP.NET synchronization context).

The implementation of the BeginProcessRequest and EndProcessRequest methods are fairly simple. The BeginProcessRequest method will instantiate the correct controller (it uses our old friend ControllerBuilder to instantiate the requested controller) and see if it implements the IAsyncController interface. If it does, then it will handle the current request asynchronously. If it doesn’t then it will simply execute that request synchronously (by invoking the SynchronizationContext.Sync method). The IAsyncController is a simple interface which adds two new methods to the ones defined on the IController method:

public interface IAsyncController : IController { 
IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state);
void EndExecute(IAsyncResult asyncResult); 

There’s really not much to say about these methods…as you might expect, the BeginExecute method will kick off the asynchronous processing and the EndExecute will be called for cleaning everything up. The easiest way to implement this interface is to inherit from the AsyncController class. Again, this class builds on the existing Controller class and adds a very interesting property (which we’ll talk more about in the future): the AsyncManager property. This property (of type AsyncManager) can be used to register asynchronous tasks and we’ll return to this topic in future posts.

Internally, the class will end up using several other auxiliary classes that are responsible for setting up the scene and trying to understand which asynchronous pattern should be used for handling the current request. I’m tempted to say that the one of the most important pieces of work is performed by the AsyncActionMethodSelector. This class is responsible for deciphering the current pattern and creating the correct action descriptor that will be responsible for invoking the current method (it ends up delegating to the traditional ReflectedActionDescriptor when none of the current available patters are found).

In the previous paragraphs, I’ve mention several times asynchronous patterns. You’ll be happy to know that the current version of the future bits (at least the one I’ve downloaded to my machine) supports three different asynchronous patterns:

  • you can define two methods (BeginXXX and EndXXX) on your controller;
  • you can also expose two methods (XXX and XXXCompleted) that handle the beginning and ending of the processing (a similar approach to the async event pattern, but without events 🙂 );
  • finally, there’s a continuation pattern where you can return a delegate from the action method that gets things started.

Before ending, there’s still time for an additional note: if you’re using IIS 6, then don’t forget to add the following to your web.config file:

<add verb="*" path="*.mvc" validate="false" type="Microsoft.Web.Mvc.MvcHttpAsyncHandler, Microsoft.Web.Mvc"/>

I think this is getting rather big and I’ll postpone some samples for the next posts 🙂 Stay tuned for more on the ASP.NET MVC.