How to use the IHttpAsyncHandler in ASP.NET

by Mads Kristensen 29. June 2008 22:47

I’ve known about the IHttpAsyncHandler interface for a long time, but never really had the time to play around with it. After a brief web search I realized that not many people have. There are no easy to understand articles or blog posts on the subject, so I thought I’d investigate and share.

Basically, the IHttpAsyncHandler interface allows you to serve content asynchronously from a HTTP handler. This is great when you need to free up the worker thread to do processing like IO work etc. ASP.NET actually uses fewer threads when it runs asynchronously, which is great for performance and scalability. That’s because each thread is returned much faster to the thread pool.

The IHttpAsyncHandler is very similar to IHttpHandler interface, but with two extra methods to override – BeginProcessRequest and EndProcessRequest. From there you invoke a delegate to handle the processing asynchronously. It sounds complicated, but it really isn’t. Here is an example that removes the complicated stuff and gives you one single method to modify.

The code

The example is a handler that is used to serve files for download. Serving a file requires IO access and therefore it is a great candidate for asynchronous serving. As you can see, the ServeContent method is all there is needed for the specific task of serving files. Just modify it to whatever purpose you find fit.

public class AsyncFileHandler : IHttpAsyncHandler

{

 

  /// <summary>

  /// You only have to modify this method.

  /// </summary>

  private void ServeContent(HttpContext context)

  {

    string filePath = context.Server.MapPath(context.Request.QueryString.ToString());

    if (File.Exists(filePath))

    {

      context.Response.TransmitFile(filePath);

    }

    else

    {

      context.Response.Write("File does not exist");

      context.Response.StatusCode = 404;

      context.Response.End();

    }

  }

 

  #region IHttpAsyncHandler Members

 

  private AsyncProcessorDelegate _Delegate;

  protected delegate void AsyncProcessorDelegate(HttpContext context);

 

  public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)

  {

    _Delegate = new AsyncProcessorDelegate(ProcessRequest);

    return _Delegate.BeginInvoke(context, cb, extraData);

  }

 

  public void EndProcessRequest(IAsyncResult result)

  {

    _Delegate.EndInvoke(result);

  }

 

  #endregion

 

  #region IHttpHandler Members

 

  public bool IsReusable

  {

    get { return true; }

  }

 

  public void ProcessRequest(HttpContext context)

  {

    ServeContent(context);

  }

 

  #endregion

}

There is actually very little reason to use the IHttpHandler interface anymore.

Important! This is an example on how to use the IHttpAsyncHandler and not to serve files. Do not use the file serving method in production code. 

Download

Download the AsyncFileHandler.cs file below and put it in the App_Code directory. Then add this XML fragment to the web.config:

<httpHandlers>
  <add verb="*" path="*file.axd" type="AsyncFileHandler" />
</httpHandlers> 

AsyncFileHandler.zip (1,14 kb)

* Only $4.95/month ASP.NET & Windows 2008 + IIS 7 Hosting! FREE SQL Included

Tags: ,

ASP.NET

Comments

6/29/2008 11:43:16 PM #

Josh Stodola

Yikes, what about security?!  Using this code, they could download the web.config and play with your emotions.

Josh Stodola United States |

6/30/2008 12:11:32 AM #

Mads Kristensen

Security was not part of this example as you also points out. The example shows how to easily use the IHttpAsyncHandler and not how to serve files.

Mads Kristensen Denmark |

6/30/2008 1:45:38 AM #

Harry M

I wrote a Comet server using it, but I was a bit disappointed as it only managed ~200 simultaneous connections on Server 2003. I haven't tested it on IIS7 but I'm hoping for better results.

Harry M United Kingdom |

6/30/2008 4:10:48 AM #

trackback

Trackback from DotNetKicks.com

How to use the IHttpAsyncHandler in ASP.NET

DotNetKicks.com |

6/30/2008 6:07:46 AM #

pingback

Pingback from rtipton.wordpress.com

Weekly Link Post 48 « Rhonda Tipton’s WebLog

rtipton.wordpress.com |

6/30/2008 8:15:56 AM #

trackback

Trackback from gOODiDEA.NET

Interesting Finds: 2008.06.30

gOODiDEA.NET |

6/30/2008 8:16:48 AM #

trackback

Trackback from gOODiDEA

Interesting Finds: 2008.06.30

gOODiDEA |

7/1/2008 2:19:30 AM #

pingback

Pingback from arjansworld.com

Arjan`s World    » LINKBLOG for June 30, 2008

arjansworld.com |

7/14/2008 6:09:47 PM #

Pradeep

How is ServeContent different from ProcessRequest method?

Can you have statement 1 in the BeginProcessRequest method instead of  statement 2?

Statement 1  : _Delegate = new AsyncProcessorDelegate(ServeContent);

Statement 2  : _Delegate = new AsyncProcessorDelegate(ProcessRequest);  

Pradeep United Kingdom |

7/14/2008 6:15:52 PM #

Mj

What's the use of using BeginInvoke here? It uses a thread from the ThreadPool which ASP.NET uses, so what's the gain? Ive implemented this using a custom threadpool, but Ive yet to see any benefits.

Mj Netherlands |

8/6/2008 9:27:06 AM #

Israel Aece

Hello Mads,

IHttpAsyncHandler provides a mechanism to invoke a costly process using async pattern. I believe that when the request came to handler, it releases the thread for the ThreadPool and grabs another thread to execute this method. When you instantiates a delegate and call BeginInvoke method, it will call the referenced method using a thread from the ThreadPool (again), where the correct would be a worker thread, so this will not improve.

Best Regards,

Israel Aece Brazil |

1/18/2009 12:07:59 AM #

ZingerNumber1

You gain nothing from this example since it's not invoking an asynchronous operation in the begin part that can be picked up in the end part. This is just lipstick on the pig. For a good example you must try to show a call to something that does begin/end - the example I studied is with Sql Server calls to SqlCommand.BeginExecuteReader.
ex: return cmd.BeginExecuteReader(....)

ZingerNumber1 United States |

Comments are closed

About the slave

Mads Kristensen Mads Kristensen
Web developer at ZYB and founder of BlogEngine.NET. More...

LinkedIn ZYB Facebook Last.fm Twitter View Mads Kristensen's profile on Technorati

The Lounge

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008