Async in Web API, Entity Framework 6 and ASP.NET Web Forms vNext

Posted by: Suprotim Agarwal , on 8/16/2013, in Category ASP.NET
Views: 65961
Abstract: A quick look at how asynchronous support is permeating though the entire Web Stack in ASP.NET vNext and that includes WebForms too!

.NET Framework 4.5 as we all know has introduced the new async and await keywords that go a long way in making Asynchronous easier. However async APIs are ‘viral’ in nature, meaning all calls up and down the call stack need to be Async. This ‘was’ a problem initially but as the APIs built on top of the Framework mature, the entire call stack is developing Async counterparts making Async usage easier. Today we’ll see how we can use the latest Async APIs all across the ASP.NET stack.

The ASP.NET Web API Sample

In today’s example, we’ll build a Web API Service that fetches data from database. We will use EF 6 beta and see all it’s Async goodness, and a WinForms client application that will create a dashboard that fetches data using the Web API services.

 

With the Basic premise out of the way, let’s get cracking. Note that we are using Visual Studio 2013 Preview.

Step 1: We start off by creating an ASP.NET Project and select the WebForms client. The reason I am selecting WebForms is to show off the Async related enhancements that are coming in Web Forms.

new-webforms-project

Now I could have selected Web API here itself but I wanted to keep the service separate and treat this application as a client or service consumer. Hence the project is named ClientApp.

Step 2: Next we add a new Project, name it Service and this time select the Web API template.

new-web-api-project

Step 3: Once the project is setup, (in the Service project) we add reference to EntityFramework 6 (currently in beta). This is because EF6 introduces Async for all calls that actually return data like Find, First, ToList, ToArray and so on.

To install EF we use the following command in the Package Manager Console.

PM> install-package EntityFramework –pre

Step 4: Next we add an Employee entity in the Models folder.

public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Email {get; set; }
}

Build the solution.

Step 5: We now scaffold an ApiController to manipulate the Employee entity. Right click on the Controller folder and select the “Scaffold…” menu item. This will bring up the following dialog

add-ef-scaffolding

Here we select the option to scaffold Web API 2 controller with EF. On clicking ‘Add’, we get the following dialog to select the Controller Name, Model class and the Data Context. Since this is our first context, we’ll have to provide a new Name. Click on ‘Add’ to complete the scaffolding process.

add-ef-scaffolding-next-step

If we take a peek at the generated Controller, we’ll see that it’s a Non-async action method using the non-async AsEnumerable() method to retrieve all the Employees using the EF DB Context.

get-employee-synchronous

Step 6: Back to the ClientApp project, we open up the Default.aspx and drop a GridView control on it. We name it Employees and as you can see below, I’ve removed the default markup that comes in the page.

default-aspx-gridview

Step 7: Before we continue with the databinding, we add an Employee entity in the ClientApp project as well. It will serve as our client ‘proxy’. In the Code behind file Default.aspx.cs we add the following code to call the Web API service, then convert the JSON returned into list of Employee objects, which are then bound to the DataGrid.

page-load-sync

All set, run the application! Initially you’ll see nothing because there is no data in the DB. I sneaked behind the scenes and added three records in the table:

data-added-to-employee-table

Now if you run the application, the Default.aspx should looks like this:

default-aspx-output

Going Async

With the synchronous implementation in place let’s make changes to go Async. We start with the Page_Load event in Default.aspx. Usually we add the async keyword to the method and then call the async version of the API (DownloadStringAsync in this case). However for the ASP.NET Page life cycle, this is not an ideal solution because adding an async makes the pipeline wait for all await calls to complete. This can potentially slow down the page cycle.

To work around this, we now have a RegisterAsyncTask helper method that takes an async function definition and hands over a Task to ASP.NET which is typically executed before the Page Pre-render. The syntax to use RegisterAsyncTask is as follows:

page-load-async

So now we have converted our client to use the API asynchronously. If we run the application now, we’ll get a YSOD!

register-async-ysod

Oops what happened? Well, we ‘forgot’ on more attribute that we have to set in the Markup (as cryptically hinted above). Open the Default.aspx and add an attribute Async=”true” to the <%@ Page … >

page-async-attribute

Now if we run the app it will run successfully. But we are not using EF’s new async features yet. Let’s do that next.

Async Entity Framework Calls

Let’s switch back to the Service project and in the DataController.cs, we can see the ToListAsync, ToArrayAsync, ToDictionaryAsync methods available in the Intellisense popup:

ef-async-calls

We update the GetEmployee method to return a Task of List<Employee> asynchronously. We add the await keyword to the ToListAsync<Employee> method to complete the ‘async-fication’ of the method.

get-employee-async

That’s about it. We are done converting our Synchronous app into an asynchronous one. Run the app and you’ll see the same output.

Key Takeaways

Before we wrap up let’s recap and consider some of the gains of async that we haven’t quantified today (we’ll do that in a separate article).

- ASP.NET vNext’s support of async enables you to use Async APIs seamlessly.

- You don’t have to do anything special to create and use Asynchronous Web API calls.

- ASP.NET takes care of thread affinity when doing Async calls. Note in the Default.aspx.cs’ Page_Load event we are calling the Service, getting data asynchronously, then binding to the DataGrid without any threading issues even though it’s possible that the data request was on thread 1 and when we awaited that call, that physical thread was assigned to some other task. When our data returned we could have been handed over to Thread 2 to complete the task. ASP.NET took care of resource marshaling.

- The one thing we didn’t measure quantitatively is performance, however, async is all about scaling and hence raw speed increases are not seen unless a lot of chained synchronous calls are parallelized.

Conclusion

With those takeaways, we conclude the today’s introduction to Async features in ASP.NET vNext and EF 6. Things are getting progressively async in the entire stack and that can only be a good thing for demanding apps that we are going to build in the future (and gives us a good reason to upgrade our current apps as well)!

Download the entire source code of this article (Github)

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Julien on Sunday, September 8, 2013 4:59 AM
Hey, thanks for this article.

I just wanted to add a small precision: the fact that you implement your service API with async tasks is independent from the fact that you consume this API asynchronously. You could very well synchronously consume an async API or asynchronously consume a synchronous API, because the HTTP layer between your API and your application will isolate them anyway.
Comment posted by zbrong on Sunday, May 11, 2014 8:49 PM
very good!
Comment posted by Shivom Bhatt on Friday, December 19, 2014 1:54 AM
I have go through the steps all done, but facing error Uh-oh, something went wrong! Error Code: 500  in about.aspx page

and while debugging it give error on downloadstring which i have passed. it show me following error
An exception of type 'System.Net.WebException' occurred in System.dll but was not handled in user code