How to Create an Asynchronous HTTP Handler in ASP.NET 4.5

Introduction

The ability to create HTTP handlers is not new to ASP.NET. However, ASP.NET 4.5 makes it easy for you to create asynchronous HTTP handlers with the new async/await keywords and Tasks. This article illustrates how an asynchronous HTTP handler can be created and consumed in an ASP.NET 4.5 web application.

Creating HTTP Handlers in ASP.NET

Traditionally HTTP handlers are classes that implement the IHttpHandler interface. You can also create an asynchronous HTTP handler by implementing the IHttpAsyncHandler interface. Asynchronous HTTP handlers are advantageous in situations where asynchronous processing can improve the overall performance of the application. The IHttpAsyncHandler interface requires you to write methods of the form BeginProcessRequest() and EndProcessRequest() methods. In ASP.NET 4.5 you can use the new async/await keywords and Tasks to achieve the same effect with simplified design.  Under ASP.NET 4.5 you can create a class that inherits from the HttpTaskAsyncHandler class and then override certain methods (as discussed later in this article).

NOTE:
Detailed discussion of async/await keywords and Tasks is beyond the scope of this article. You may read Working with Asynchronous Operations in ASP.NET 4.5 Web Forms for the basic understanding of these concepts.

Sample Asynchronous HTTP Handler

To understand how asynchronous HTTP handlers are created in ASP.NET 4.5, let's develop a simple example. Suppose that you have an ASP.NET web site with one or more web forms. On each of the web forms you wish to display advertisements. The advertisements are not statically placed on the web forms. They reside in a SQL Server database and at runtime you need to fetch them so as to render them onto the pages. Additionally, you also need to track the impressions each advertisement is receiving.

The following figure shows the Entity Framework for the sample database tables Ads and AdStats.

The Entity Framework

The Entity Framework

As you can see the Ads table has only two columns, viz. Id and Markup. The Markup column contains the HTML markup of the advertisement. The AdStats table stores information about ad impressions such as UserIP, UserAgent and TargetUrl.

To display an advertisement on web forms and to track the ad statistics you will create an asynchronous HTTP handler. In this specific scenario, creating an asynchronous HTTP handler rather than a synchronous one is beneficial because the ads are independent of the web form content and can be processed asynchronously. To create the asynchronous HTTP handler add a new Generic Handler (*.ashx) to the web application.

Add a new Generic Handler

Add a new Generic Handler

Change the default definition of the Generic Handler class as shown below:

<%@ WebHandler Language="C#" Class="MyHandler" %>

using System;
using System.Web;
using System.Threading.Tasks;
using System.Linq;

public class MyHandler : HttpTaskAsyncHandler
{
   ...
}

As shown above the MyHandler class inherits from the HttpTaskAsyncHandler base class. The HttpTaskAsyncHandler class is provided by ASP.NET 4.5 and you need to override its ProcessRequestAsync() method. The following code shows a sample implementation of the overridden method:

public override async Task ProcessRequestAsync(HttpContext context)
{
    string userIP = context.Request["REMOTE_ADDR"];
    string targetUrl = context.Request.QueryString["url"];
    string userAgent = context.Request.Browser.Browser;

    string adMarkup = await GetAdAsync();
    context.Response.Write("document.write('" + adMarkup + "');");
        
    string result = await SetStatsAsync(targetUrl, userIP, userAgent);
}

 As you can see the ProcessRequestAsync() method is an asynchronous method. Inside ProcessRequestAsync(), details about the web form requesting an advertisement are captured. These details include the user's IP address, the URL of the target web form and the requesting browser. The code then gets the details of advertisement from the database by calling the GetAdAsync() method. It also saves the ad statistics to the database by calling the SetStatsAsync() method.

The GetAdAsync() and SetStatsAsync() methods are quite similar in nature and are shown below.

private async Task<string> GetAdAsync()
{
    var func = Task<string>.Factory.StartNew(() => GetAdFromDb());
    await func;
    return func.Result;
}
private async Task<string> SetStatsAsync(string targeturl, string userip, string useragent)
{
    var func = Task<string>.Factory.StartNew(() => SaveStatsToDb(targeturl,userip,useragent)); 
    await func;
    return func.Result;
}

Both of these methods start a new Task and run the actual database access code on it using two helper methods: GetAdFromDb() and SaveStatsToDb(). These helper methods are shown below.

private string GetAdFromDb()
{
    System.Threading.Thread.Sleep(5000);
    DatabaseEntities db=new DatabaseEntities();
    var data = (from item in db.Ads
                select item).SingleOrDefault();
        
    return data.Markup;
}
private string SaveStatsToDb(string targeturl, string userip, string useragent)
{
    DatabaseEntities db = new DatabaseEntities();
    AdStat stat = new AdStat();
    stat.AdId = 1;
    stat.TargetUrl = targeturl;
    stat.UserIP = userip;
    stat.UserAgent = useragent;
    db.AdStats.Add(stat);
    db.SaveChanges();
        
    return "Data saved successfully!";
}

The GetAdFromDb() method simply retrieves the first record from the Ads table. In a real world situation you will have some ad selection logic here. It then returns the ad Markup to the caller. Notice that the GetAdFromDb() method introduces a delay of 5 seconds by calling the Sleep() method. This is done purely for the purpose of testing and you can remove this line once the application is complete. The SaveStatsToDb() method stores the target URL, user's IP and user agent (browser) to the AdStats table.

Using the Sample HTTP Handler in a Web Form

Now that your asynchronous HTTP handler is ready, let's see how it can be used in a web form. Add a web form to the web application and place a <script> tag in it as shown below.

<script type="text/javascript" src="http://localhost:49183/AsyncHTTPModuleHandler/MyHandler.ashx?url=<%= Request.Path%>">
</script>

As you can see the <script> tag points to the MyHandler.ashx, the asynchronous HTTP handler you developed in the previous section. It also passes the Request.Path of the current web form in a querystring parameter. This way you are making a call to the asynchronous HTTP handler where the <script> tag is placed.

Before running the web form, add some advertisement data in the Ads table and then run the web form. The following figure shows a sample run of the web form.

Sample run of a web form

Sample run of a web form

As you can see from the above figure the text "Hello World!" is part of the web form whereas the text "This is an advertisement!" is the part of an advertisement and is stored in the database. Also notice that when you run this web form "Hello World!" is displayed immediately and the advertisement is displayed after 5 seconds due to the delay introduced in the code. After running the web form check the database to verify the ad statistics are stored as expected.

Summary

ASP.NET 4.5 allows you to create asynchronous HTTP handlers easily. An asynchronous HTTP handler is a class that inherits from the HttpTaskAsyncHandler base class. This article illustrated how an asynchronous HTTP handler can be created and consumed in a web forms application.



Related Articles

Downloads

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

Most Popular Programming Stories

More for Developers

RSS Feeds

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