Creating Asynchronous Actions in ASP.NET MVC


Asynchronous actions allow you to handle more concurrent requests and can be implemented using async / await keywords. Asynchronous actions are useful in situations where you are performing some network operation such as calling a remote service. This article discusses asynchronous actions and also shows how to create them in an ASP.NET MVC.

Overview of Asynchronous Actions

Before you create an asynchronous action, let's quickly understand what asynchronous processing is with respect to ASP.NET MVC and how it is beneficial to your application.

Suppose that you are developing an ASP.NET MVC application that heavily relies on some third-party service. Consider the following action method as an example:

public ActionResult Index()
    DbHelper helper = new DbHelper();
    List<Customer> data = helper.GetCustomerData();
    return View(data);

The above code shows an Index() action method that returns an ActionResult. Inside, it creates an instance of a helper class (DbHelper) and calls its GetCustomerData() method. The GetCustomerData() method wraps the remote service call and returns the data returned by the service as a List of Customer objects. The data is then passed to the Index view as its model.

The Index() action method shown above executes in asynchronous manner. When a request lands to the Index() action, ASP.NET picks up a thread from its thread pool and runs the Index() method on the allotted thread. Since Index() action is synchronous, all the operations, including the remote service call, happen sequentially (one after the other). Once all the operations are over, the thread running the code can be reused for some other execution. Thus a thread from the thread pool is blocked for the entire duration of the execution - start to end. Let's say this execution takes 10 seconds (just a hypothetical value).

Now assume that the Index() and GetCustomerData() method has been modified to work in asynchronous manner. When a request lands to the Index() action, ASP.NET picks up a thread from the thread pool as before. The Index() method starts running on a thread allotted to it. However, the allotted thread invokes the GetCustomerData() asynchronously and is immediately returned to the thread pool to serve other requests. When the remote service call returns the required data, another thread from the thread pool is allotted to finish the remainder of the Index() method code. Thus instead of blocking a thread for the entire duration of the processing, a thread is released as soon as the network operation starts and the processing resumes on some other thread when the network operation returns. Even in this case the total time taken for the processing is 10 seconds but the thread is freed to serve other requests. This results in improved handling of concurrent requests. Although there may not be any performance improvement as far as single requests processing time is concerned, the overall performance of the application may be better than before because there is less queuing of requests.

Synchronous operations are good when you wish to stick to a a simple programming model, operations are short running and CPU centric. On the other hand, asynchronous operations are good when concurrent request handling is more important than simplicity, operations are long running and network centric (such as remote Web API or service calls). 

Creating Asynchronous Actions

Now that you know the basics of asynchronous action methods, let's create an asynchronous action method using async / await keywords of C#. To begin developing this sample application, create a new ASP.NET MVC application using empty project template. Then add an ADO.NET Entity Data Model for the Customers table of the Northwind database. The following figure shows this data model:

Customers table
Customers table

Then add a class to the project and name it DbHelper. This class contains the GetCustomerDataAsync() method as shown below:

public class DbHelper
    public async Task<List<Customer>> GetCustomerDataAsync()
        NorthwindEntities db = new NorthwindEntities();
        var query = from c in db.Customers
                    orderby c.CustomerID ascending
                    select c;
        List<Customer> data = await query.ToListAsync();
        return data;

This application doesn't use any real network operation such as a service call. Just for the sake of testing, it fetches all the customers from the Customers table and returns to the caller.

The GetCustomerDataAsync() method returns a Task object that wraps a generic List of Customer entities. The GetCustomerData() is marked with the async keyword indicating that it is to be called in asynchronous manner. Since the method is asynchronous the method name ends with "Async". Inside, a LINQ to Entities query is formed that fetches all the customers from the database. Notice that the data is realized by calling ToListAsync() method. The await keyword used in the ToListAsync() statement indicates that the execution should wait for ToListAsync() to complete. The List of Customer entities is then returned to the caller.

Now, add a controller to the Controllers folder and add the following code to it:

public async Task<ActionResult> IndexAsync()
    DbHelper helper = new DbHelper();
    List<Customer> data = await helper.GetCustomerDataAsync();
    return View(data);

This is the same Index() action you saw earlier but now it has been converted to its asynchronous version. The IndexAsync() method returns a Task object that wraps the ActionResult. It is also marked with an async keyword. Inside, it creates an instance of DbHelper class and calls the GetCustomerDataAsync() method. Notice the use of the await keyword. You will find that async and await always go hand in hand.

Now, add IndexAsync view to the project and add the following markup to it:

@model List<AsyncMVCDemo.Models.Customer>

    Layout = null;

<!DOCTYPE html>

    <meta name="viewport" content="width=device-width" />
    <h1>List of Customers</h1>
    <table border="1" cellpadding="6">
        @foreach(var customer in Model)

If you run the IndexAsync() action method you should get a list of customers displayed in a table (see below).

A list of customers
A list of customers

Dealing with Timeouts

While working with asynchronous operations you should take into account the possibility that a call is made that never returns. To tackle such situations ASP.NET MVC provides the [AsyncTimeout] attribute. The [AsyncTimeout] attribute specifies a timeout value in milliseconds for the asynchronous operation. The default timeout value is 45 seconds. Although we won't get into more detail of the [AsyncTimeout] here, you can use it as follows:

public async Task<ActionResult> IndexAsync()

The above code sets the timeout value to 2000 milliseconds. Just in case you don't want to have any timeout or the asynchronous operation you can use the [NoAsyncTimeout] attribute.

public async Task<ActionResult> IndexAsync()


ASP.NET MVC makes it easy for you to create asynchronous action methods by following the async / await pattern of .NET framework 4.5. Asynchronous operations allow action methods to cater to more concurrent requests than otherwise. Asynchronous action methods are useful for tasks involving network operations such as calling a remote service.

Related Articles


  • Is it necessary is it is only one call from controller

    Posted by Aswin on 08/15/2016 12:49pm

    If your controller has only one service method call then is it necessary to make async call. For e.g. List data = helper.GetCustomerData(); Since we have only one call, what is the point of going async. I understand if we have multiple backend calls like List data = helper.GetCustomerData(); List data1 = helper.GetCustomerData1(); then it makes sense to go async so that second call doesn't have to wait until first is done.

  • Thank you

    Posted by pranit on 04/13/2015 03:52am

    Thanks for the blog. It clears basic concept about async await

  • Thanks

    Posted by Francisco on 04/10/2015 07:43am

    Thanks dude this help me, For the ones who cant get .ToListAsync() method, you should add the library : System.Data.Entity; Sou you add in you proyect/Controller = using System.Data.Entity;

  • Chain of Commands for Task<> - Is it necessary?

    Posted by Amit Karmakar on 03/27/2015 10:06am

    Great Article !!! I was wondering if we really need to complicate the helper method itself to return Task. Can we not keep the helper layer simple and instead call make the synchronous call at the Controller Action only. Something like: public async Task IndexAsync() { return await Task.Run(() = { DbHelper helper = new DbHelper(); List data = helper.GetCustomerData(); return View(data); }); } This way - the subsequent layers can be implemented as normal object types and the complexity of asynchronous call is left alone only at Controller class.


    Posted by SIAMAK on 02/20/2015 03:23am

    Thank you, really great

  • fixed matches

    Posted by fixed matches on 01/29/2015 04:33am

    Hey there owner of Great site. I think you should be little more strict with the comments.

  • Simple explanation for Async programming

    Posted by Dhanuka on 01/01/2015 10:23pm

    Thanks a lot, this is very simple and very useful. All my team mates referred to this article. Keep it up!

  • Nice article (a suggestion)

    Posted by SpiderCode on 11/19/2014 08:59pm

    Hello Bipin Joshi, Its a very nice article written. Enjoyed it while reading. Apart from this, I found there is a small mistake (Not sure). In your blog, you have written that "The Index() action method shown above executes in asynchronous manner", it does not execute in asynchronous manner, it will be executed in synchronous manner :)

  • Calling async method

    Posted by Guest1 on 11/11/2014 03:22am

    lets say i have an action public ActionResult Submit(EmpModel formModel, string SubmitForm) { IndexSync(); // how to call the async method from another action. }

  • Confused

    Posted by Logan on 07/05/2014 08:21am

    Where does .ToListAsync() come from? I'm getting a "does not contain a definition for .ToListAsync" error... Also, where I declare my actions (ie. public async Task GetUsers()), its telling me "Cannot find all types required by the 'async' modifier...

  • Loading, Please Wait ...

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

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date