Implementing Asynchronous Operations in ASP.NET MVC Framework

Introduction

The Model View Controller Design pattern can be used to isolate the application's business logic from its user interface components. This promotes loose coupling and lesser cohesion amongst the components and as a result, the components of the application become easier to test and maintain. This article is an attempt to illustrate how you can implement asynchronous operations in your ASP.NET MVC applications.

Pre-requisites

To use the code examples illustrated in this article, you should have the following installed in your system:

  • Microsoft Visual Studio 2010 RC or higher
  • ASP.NET MVC Framework 2.0 or higher

What is the Model View Controller Design Pattern?

The Wikipedia states: "Model-View-Controller (MVC) is a software architecture, currently considered an architectural pattern used in software engineering. The pattern isolates "domain logic" (the application logic for the user) from input and presentation (GUI), permitting independent development, testing and maintenance of each." Reference: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Applications that have a mix of data access, business logic and presentation layer code are difficult to test and maintain because of the interdependencies amongst the components. A change in any of said components would incur a change in the components that depend on the component that has changed. The MVC Design Pattern solves these problems by reducing the cohesion amongst the components in an application. It does this by decoupling the data access, business logic, and data presentation and user interaction components resulting in loosely coupled and easily testable components.

A lot of frameworks have been designed based on this design pattern. These include: ASP.NET MVC Framework, Ruby on Rails, Merb, Struts, Spring, and Django.

The architectural components of the MVC Design include:

  • Model - this comprises the application's business logic and data access components
  • View - this includes the application's user interface components
  • Controller - this layer is responsible for handling the interaction amongst the other two components, handling user interactions, changing model state and invalidating the view based on the model's data.

A Quick Tour of the ASP.NET MVC Framework

ASP.NET MVC Framework is one of the most exciting advancements in Microsoft Web Technologies since ASP.NET came into the market way back in 2002. The ASP.NET MVC Framework is based on the proven, tested and popular Model View Controller (commonly known as MVC) design pattern.

The ASP.NET MVC Framework provides support for the following features:

  • Support for a Test Driven Design model
  • Support for Dependency Injection and IOC containers
  • Support for clean URLs and navigation support
  • Support for REST-based design
  • Pluggable, extensible, and maintainable
  • Support for all existing ASP.NET features that includes, authentication, authorization, membership and role management, state management, etc

The ASP.NET MVC Framework provides you a paradigm shift from the way web applications are designed in ASP.NET. You can use this framework to design and implement web applications in a more structured way, make them testable, maintainable and extendable and using less code.

What are Synchronous and Asynchronous Operations?

What are synchronous and asynchronous operations and when should you decide to have methods that make synchronous or asynchronous calls? Applications are CPU bound, I/O bound or a mix of both. The decision of opting for synchronous or asynchronous operations depends on to what extent the operation is CPU or I/O intensive. You can use synchronous methods or operations when the operations are short-running, are CPU bound operations and their implementation needs to be simple. There is no point in using asynchronous methods for performing CPU bound operations as it would result in more overhead.

You can use asynchronous operations or methods when the operations are long-running, are more I/O bound and also when parallelism is preferred over simplicity of code to eliminate blocking operations. Most importantly, you can use asynchronous operations to allow the user to cancel the operation if need be. Note that intensive I/O operations can result in blocking operations if they are called synchronously as I/O operations take longer time to complete. Typical examples of intensive time consuming I/O operations include, database operations, reading and writing to disk files, calling external web services, etc.

What happens when an asynchronous operation is invoked? When an asynchronous action method is invoked, the IIS (if you are using IIS as your web server) web server fetches a worker thread from the thread pool and uses this thread to handle the incoming request. A thread pool is a pool of ready to use worker threads. The asynchronous operation is executed on this worker thread. Note that a worker thread is one that is executed in the background. An application can have only one application or main thread but multiple worker threads. Now, the worker thread is returned to the thread pool and when the asynchronous operation completes, the ASP.NET runtime is notified. Now the web server fetches another worker thread from the thread pool to process the remaining part of the request and executes the remaining request cycle. Note that this worker thread can be the same that initiated the asynchronous operation, or, it can be a different worker thread.

Implementing Asynchronous Operations in ASP.NET MVC Applications

To implement operations in ASP.NET MVC Framework you should extend your controllers from the abstract AsyncController class. Here's how this class looks like:

   public abstract class AsyncController : Controller, IAsyncManagerContainer, IAsyncController, IController
       {
           protected AsyncController();
           public AsyncManager AsyncManager { get; }
           protected virtual IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state);
           protected virtual IAsyncResult BeginExecuteCore(AsyncCallback callback, object state);
           protected override IActionInvoker CreateActionInvoker();
           protected virtual void EndExecute(IAsyncResult asyncResult);
           protected virtual void EndExecuteCore(IAsyncResult asyncResult);
       }
 

The AsyncManager class belongs to the System.Web.Mvc.Async namespace and provides the necessary operations for the AsyncController class.

You can write your controller in ASP.NET MVC 2 by deriving from the AsyncController class as shown below:

  public class HomeController : AsyncController
  {
      //Some code
  }

Note that the name of an asynchronous controller class should have the "Controller" suffix. As an example, Home controller can be named HomeController but not "Home" or "ControllerHome". Also, you cannot have both the synchronous and asynchronous versions of the same method reside in the same controller. As an example, you cannot have "Index" and "IndexAsync" reside in the same controller class. If you do, an AmbiguousMatchException exception will be thrown as the synchronous and asynchronous versions of the same action method will have the same signature.

The following code snippet illustrates a synchronous controller and its action method:

  public class ProductsController: Controller 
  {
      public ActionResult LatestProducts(int productCode) 
      {
        //Some code
      }
  }

To convert the above action method to an asynchronous action method, all you have to do is, extend the controller from the AsyncController class and rename the action method with "Async" suffix. Here's how you can rewrite it:

  public class ProductsController: AsyncController 
  {
      public ActionResult LatestProductsAsync(int productCode) 
      {
        //Some code
      }
  }

The actions that execute asynchronously are methods of a class that extends the AsyncController class. An async action comprises of a pair of two methods that have the "Async" and "Completed" suffixes respectively.

  public class HomeController : AsyncController 
  {   
   public void GetProductsAsync() 
   { 
     //Some code
   } 
  
   public ActionResult GetProductsCompleted(IList<Product> items) 
   { 
        //Some code
   } 
  }

Also, to define a route to handle a request asynchronously, use the AsyncMvcRouteHandler, instead of usual MvcRouteHandler as shown below:

  routes.Add(new Route("Default.aspx", new AsyncMvcRouteHandler())
  {
      Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),
  });

Suggested Readings

http://weblogs.asp.net/scottgu/archive/2010/01/10/asp-net-mvc-2.aspx
http://www.asp.net/mvc/whatisaspmvc

Summary

Asynchronous operations if used judiciously can help you improve the scalability and user experience of an application. You can use asynchronous operations in ASP.NET MVC applications to improve the user experience and application's scalability. In this article we have had a look at synchronous and asynchronous operations and how the later can be implemented in ASP.NET MVC applications.

Related Articles



About the Author

Joydip Kanjilal

Microsoft Most Valuable Professional, Author and Speaker. Featured in "MSDN Featured Developer of the Fortnight (India)" a number of times. Winner of Community Credit Awards at www.community-credit.com several times. Authored numerous books and articles in Microsoft .NET and its related technologies. Authored the following books:-- ASP.NET 4.0 Programming (Mc-Graw Hill Publishing) Entity Framework Tutorial (Packt Publishing) Pro Sync Framework (APRESS) Sams Teach Yourself ASP.NET Ajax in 24 Hours (Sams Publishing) ASP.NET Data Presentation Controls Essentials (Packt Publishing)

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • QA teams don't have time to test everything yet they can't afford to ship buggy code. Learn how Coverity can help organizations shrink their testing cycles and reduce regression risk by focusing their manual and automated testing based on the impact of change.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds