Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Writing Asynchronous HTTP Module in ASP.NET 4.5

4.33/5 (4 votes)
25 Apr 2012CPOL4 min read 42.5K  
Asynchronous HTTP Module - one of the new features that got enhanced in ASP.NET 4.5

Introduction

In this post, I am going to discuss one of the new features that got enhanced in ASP.NET 4.5. It is Asynchronous HTTP Module and it’s going to be very useful if used meticulously.

First, I would just like to give a brief idea why Asynchronous HTTPModules are important?

As we all know, web is stateless. A Web page is created from scratch every time it is posted back to the server. In traditional web programming, all the information within the page and control gets wiped off on every postback. Every request in ASP.NET goes through a series of events.

Every request is served by an HTTP handler and it goes a series of HTTPModules (HTTPPipeline) which can be read, update the request. A lot of features of ASP.NET like Authentication, Authorization, Session, etc. are implemented as HTTP Module in ASP.NET. Let’s have a view on the Request Processing.

Image 1

ASP.NET Request Processing : HTTPPipeline and HTTPHandler

Now as you can see, the request is assigned to a thread T1 from the available threads in the thread pool. And the request is passed through several HTTPModules and finally served my HTTPHandler and response is send back with the same thread (T1).

During the entire processing, the same thread is engaged in serving the same request and cannot be used by any another request till request processing completes. During the request processing, if any HTTPModules depends on some entities like I/O based operations, web services, databases queries, etc., then it takes long to complete which makes the thread busy for long which makes ASP.NET thread not do anything during that duration and will be useless. In this kind of scenario, the throughput goes down rapidly.

In the above scenario, synchronous HTTPModule can degrade the site performance a lot. So if we can make HTTPModules as asynchronous, that can increase the throughput a lot. In asynchronous mode, ASP.NET thread gets released as soon as the control gets passed to another component/module, it does not wait. And the thread becomes available in thread pool and can be used to serve another request. When the component completes its assigned task, then it gets assigned to a new ASP.NET thread which completes the request. The flow can be graphically presented as:

Image 2

Working of an asynchronous HTTPModule

In the above picture, an ASP.NET thread T1 is assigned from threadpool to server the request. When the control gets passed to File System to log message, ASP.NET thread gets released and when message logging gets completed, control passes to ASP.NET and it is assigned to another thread, say T2 from thread pool.
In .NET Framework 4.0, there was some major enhancement made for asynchronous programming model. Any asynchronous operation represents a Task and it comes under the namespace System.Threading.Tasks.Task.

In .NET 4.5, there are some new operators and keywords introduced that make life easy for implementing Asynchronous feature. One is async keyword and await operator.

These two enable us to write the asynchronous code in a similar fashion as we write for synchronous mode.

And these features can be easily used while writing HTTPModules and HTTPHandlers. We’ll be using these enhancements in writing our custom asynchronous HTTPModule.

In my sample as depicted in the image, I am creating a module that writes some log messages in a text file for every request made.

So to create a Custom HTTPModule, create a class library project. And create a class say named LogModule which implements IHttpModule. For this, you need to add a reference of Assembly System.Web.

LogModule would contain the methods discussed below.

We need to implement two methods Init and Dispose that are part of IHTTPModule interface.

Here first, I have written an asynchronous method that actually reads the information from the request and writes in the log file asynchronously. For this, I have used WriteAsync of FileStream.

C#
private async Task WriteLogmessages(object sender, EventArgs e)
{
	HttpApplication app = (HttpApplication)sender;
        DateTime time = DateTime.Now;

        string line = String.Format(
        "{0,10:d}    {1,11:T}    {2, 32}   {3}\r\n",
        time, time,
        app.Request.UserHostAddress,
        app.Request.Url);
        using (_file = new FileStream(
            HttpContext.Current.Server.MapPath(
              "~/App_Data/RequestLog.txt"),
            FileMode.OpenOrCreate, FileAccess.Write,
            FileShare.Write, 1024, true))
        {
            line = line + "  ," + threaddetails;
            byte[] output = Encoding.ASCII.GetBytes(line);

            _file.Seek(_position, SeekOrigin.Begin);
            _position += output.Length;
            await _file.WriteAsync(output, 0, output.Length);
        }
}

Here, you can see the await keyword, what it means...

As per MSDN:

An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

await is used with some asynchronous method that returns task and is used to suspend the execution of the method until the task completes and control is returned back to the caller to execute further. await should be used with the last expression of any code block.

And Init method would be like:

C#
public void Init(HttpApplication context)
{
        // It wraps the Task-based method
        EventHandlerTaskAsyncHelper asyncHelper =
           new EventHandlerTaskAsyncHelper(WriteLogmessages);

        //asyncHelper's BeginEventHandler and EndEventHandler eventhandler that is used
        //as Begin and End methods for Asynchronous HTTP modules
        context.AddOnPostAuthorizeRequestAsync(
        asyncHelper.BeginEventHandler, asyncHelper.EndEventHandler);
}

So apart from the above methods, we need to implement the dispose method.

Now compile your class library and use the reference in your ASP.NET website. Now as you must be knowing, we need to need to add the entry in the config file. So it’ll be as:

C#
<system.webServer>
<modules>
<add name="MyCustomHTTPModule" type="MyCustomHTTPModule.LogModule, MyCustomHTTPModule"/>
</modules>
</system.webServer>

Now when you run your application, you will see the logs are created in a text file in App_Data folder as mentioned path in the code.

Hope you liked this new feature!

History

  • 25th April, 2012: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)