LA.NET [EN]

Apr 02

The MVC framework: the IAsyncResult pattern

Posted in ASP.NET MVC      Comments Off on The MVC framework: the IAsyncResult pattern

In this post we’re going to keep looking at the asynchronous features introduced by the MVC futures and we’ll see an example of how to use the IAsyncResult pattern for adding an asynchronous action to a controller. The idea is simple: you need to add two methods with the following signatures:

public IAsyncResult BeginActionMethod(Int32 id, AsyncCallback callback, Object state);
public ActionResult EndActionMethod(IAsyncResult asyncResult);

This is the expected asynchronous version of the traditional synchronous methods you generally end up using on the ASP.NET MVC applications. To illustrate its use, we’re going to change the default HomeController you get when you create a new ASP.NET MVC project and add a new method which gets the HTML returned from an existing url. Lets start with the changes we’ll be doing to the Index view:

% using( var frm = Html.BeginForm( "GetHtml", "Home") )
{%>
  <label for="url">Url: </label>
  <%=Html.TextBox("url")%>
  <input type="submit" value="Get html" />
<%
}%>

Nothing new here: just a simple form which submits itself to a GetHtml action method on the Home controller. Now, the interesting part. Here’s the code we’ve added to the controller:

public IAsyncResult BeginGetHtml(String url, AsyncCallback cb, Object state)  {
  var req = WebRequest.Create(url,,);
  req.Method = "GET"; 
  return req.BeginGetResponse(cb, req);
}

public ActionResult EndGetHtml(IAsyncResult ar) {
  var req = ar.AsyncState as WebRequest;
  var response = req.EndGetResponse(ar);
  using (var reader = new StreamReader( response.GetResponseStream() ) ) {
     ViewData["contents"] = reader.ReadToEnd();
  }
  return View( "Index" );
}

The most interesting thing is that the method signature can be slightly changed so that you get all the goodies you’re used to in the synchronous model (ie, you can still have automatic binding between the method’s parameters and the form’s submitted values).

As you can see, we’re returning the IAsyncResult object that resulted from the call to the BeginGetResponse method (notice also the chain of callbacks in the BeginGetHtml method: we don’t pass our callback method to it; instead, we’re passing the callback method that we’ve received in our method – parameter cb). The EndGetHtml method is also pretty simple: we’re just getting the response and translating it into a string. Finally, we return the ActionResult that will render our view. btw, you should also add something like this to the Index view:

<%= Html.Encode(ViewData["contents"]  ) %>

This ensures that you’ll see the return HTML on your view.

There are some things you should keep in mind when using this approach:

  • filter attributes must be placed in the begin method;
  • even though you can apply the ActionNameAttribute to the BeginXXX method, the End method must match the real method name (and not the alias you’ve created by using the ActionNameAttribute);
  • You can’t call Begin methods directly when using asynchronous controllers. If you need that, you’ll have to use the previous attribute (ActionNameAttribute) to create that illusion.

And that’s all for today…more on asynchronous calls in the next posts. Keep tuned.