microsoft press home   All Products  |   Support  |   Search  |   microsoft.com Home  
 
  Microsoft Press Home  |   Register Books  |   Site Index  |   All Books  |

 

Advanced Search
Hot topics:
Books about:
Books for:
Products for:



Developer Featured Article
Serving Up ASP.NET Handlers the Easy Way
Serving Up ASP.NET Handlers the Easy Way By Scott Mauvais, MCSE, MCSD, MCDBA

Over the past few months I have covered many of the exciting new features in Microsoft® Windows® Server 2003 that application developers will find most interesting. For example, I have discussed the integration of the Microsoft .NET Framework into the operating system, the new application server role, and the performance and reliability improvements in Internet Information Server 6.0. While new operating systemping for developers: code.

In that vein, this month I am going to walk you through one more interesting and powerful feature of ASP.NET that for some reason has not gotten that much attention: HTTP handlers. You can use handlers to do everything from mapping file extensions to some custom logic all the way up to more complex tasks such as watermarking images and asynchronous processing. My goal in this article is to first introduce you to the functionality that handlers provide. Next I will walk you through creating a simple handler, and then I will look at the steps required to write and register custom handlers.
 

As you might expect, there is much more to this topic than I can cover in this article. To learn more about handlers and how they fit into the rest of the ASP.NET development model, you will want to pick up a copy of Developing Microsoft ASP.NET Server Controls and Components by Nikhil Kothari and Vandana Datye. Besides explaining the ins and outs of extending the functionality of ASP.NET by creating custom server controls, they include an entire chapter devoted to HTTP handlers. To get a feel for the book, you can review the table of contents and even read a sample chapter on Developing a Simple Custom Control.

HTTP Handler Architecture

HTTP handlers provide two key benefits over the standard ASP.NET development model. First off, handlers provide you with greater control over the actual interaction with the client because they give you direct access to the raw HTTP requests. For example, if your client application is not a browser but rather some arbitrary application, you can send just the data it needs. This way, the client app does not need to worry about extracting the data from all the noise that makes up a typical HTML response. The second benefit is performance. With HTTP handlers, you will see a bit of a performance gain over standard ASPX files because you can bypass some overhead, including the Page class which all Web Forms must inherit.

If you are familiar with ISAPI development, you'll see that an HTTP handler is very similar to an ISAPI Extension. Astute readers may wonder why I think HTTP handlers are such a big deal given that ISAPI has been around since the IIS 2.0 days-and that was a long time ago. The simple answer is: ISAPI development is hard. To write an ISAPI application, you need to be a pretty accomplished C++ programmer who is comfortable developing multi-threaded server applications. Debugging ISAPI apps is notoriously difficult, and minor coding mistakes can quickly lead to memory leaks and unhandled exceptions that crash your application. To make matters even worse, because ISAPI filters run in the same memory space as the Web server itself, such errors will often bring down the entire Web server.

HTTP handlers, on the other hand, are written in managed code, so you gain the benefits provided by the .NET Framework and CLR such as easy debugging, type safety, garbage collection, and the Base Class Libraries.

Enough talk-let's look at the code.
 

Writing a Simple HTTP handler

At its most basic level, an HTTP handler is nothing more than a class that implements the IHttpHandler interface. The following example shows a very simple HTTP handler written in C#:

<% @ webhandler language="C#" class="SimpleHandler" %>

using System;
using System.Web;

public class SimpleHandler: IHttpHandler
{
  public bool IsReusable
  { get { return false; } }

  public void ProcessRequest(HttpContext ctx)
  {
    ctx.Response.Write("Hello, I'm a simple handler");
  }
}

Let's walk the steps required to execute this handler. The first step is to create a new file called SimpleHandler.ashx and drop it in your Web root. Note that the ASHX extension signifies that the file represents an HTTP handler. Later on, I'll show you how the Web server makes this association but for the time being the specifics are not important. You will want to start off with the webhandler directive that tells ASP.NET that the file contains an HTTP handler and the class directive specifies the class that implements it, in this example SimpleHandler.

Now it's time to write the handler itself. To do this you create the class SimpleHandler and implement the IHttpHandler interface from the System.Web namespace. The interface itself is extremely simple; you need to implement only two things: the IsReusable property, which is read-only, and the ProcessRequest method, which does the heavy lifting. To keep things simple, keep the IsReusable property as false.

You'll notice that ProcessRequest receives a single argument, which is an HttpContext class. This class provides access to the intrinsic server objects such as Request, Response, and Server. This sample uses the Response object's Write() method to send some test back to the client app. For the complete documentation of IHttpHandler interface, see the online documentation on MSDN®.

That's all it takes to write a simple HTTP handler.
 

Writing a Custom HTTP Handler

As it turns out, the process for writing a custom handler is nearly identical to writing a simple one. The only real differences are that you create the class in your own namespace and don't include the directive syntax as shown in this example of a more complex handler:

using System;
using System.Web;

namespace Mauvais.Samples.MSPress
{
  public class ComplexHandler : IHttpHandler
  {
    public bool IsReusable
    { get { return false; } }

    public void ProcessRequest(HttpContext ctx)
    {
       string url = ctx.Request.RawUrl;
       int ext = url.ToLower().LastIndexOf(".mspress" ) -1 ;

       ctx.Response.Write("Hello, " + url.Substring(1, ext) + "!");
    }
  }
}

This code simply strips the .mspress extension off the raw ULR and echoes it back.

With the code being so similar, the main difference between the two is in the implementation. A simple handler is bound to a specific file name such as SimpleHandler.ashx while a custom handler is bound to a file pattern. In other words, the only way to access your simple handler is http://localhost/SimpleHandler.ashx. On the other hand, you can execute a custom handler by referencing any URL that matches the file pattern to which your handler is bound. For example, if you bind your handler to the .mspress extension, either of the following URLs would work: http://localhost/Scott.mspress or http://localhost/Dave.mspress.

As I mentioned earlier, ASP.NET automatically knows that files with a .ASHX extension are implemented as handlers. The reason for this is two-fold. First, when you install the .NET Framework, it adds an application extension mapping to IIS which associates .ashx with aspnet_isapi.dll. Second, machine.config specifically maps the .ASHX extension to the System.Web.UI.SimpleHandlerFactory class. If you look through the section of machine.config, you will see that many common ASP.NET extensions such as .aspx, .asmx, and trace.axd are implemented as handlers. Even more interesting, extensions for sensitive files such as .config, .vb, and .cs are mapped to a class called System.Web.HttpForbiddenHandler which prevents those files from being downloaded.

To configure your server to use your handler for requests ending in .mspress, you need to compile and deploy your code, add an entry in your web.config to associate .mspress with your class, and configure a new application extension in IIS.

To test this, compile the code of the complex handler example and copy the DLL to the Bin directory off your Web root. Next you will want to create the following web.config file in your Web root:

<configuration>
  <system.web>
     <httpHandlers>
        <add verb="GET"
             path="*.mspress"
             type="Mauvais.Samples.MSPress.ComplexHandler,
                   ComplexHandler"/>
     </httpHandlers>
  </system.web >

The path attribute specifies the extensions that it will handle. Note that the type is a two-part value: the first part identifies the namespace and class that will implement the handler, and the second part provides the assembly name. You will need to be sure that the assembly itself is located in the application's search path. Verb refers to the HTTP verbs that it will handle. If you want to process all verbs, you would use an asterisk; in this example, HTTP verbs are limited to GET requests.

Finally, you need to add the application extension in IIS. To do this, fire up Internet Information Services Manager and navigate to your default Web site, right-click, and select Properties. Select the Home Directory tab, and click on Configuration as shown in Figure 1.

Figure 1: You must modify the Default Web Site Properties to add a custom handler.

Figure 1: You must modify the Default Web Site Properties to add a custom handler.

In the Application Configuration window, click the Add button to bring up the Add/Edit Application Extension Mapping dialog shown in Figure 2. In this dialog box, click the Browse button and navigate to aspnet_isapi.dll, which in the case of the .NET Framework version 1.0 is located by default in c:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\aspnet_isapi.dll. In the Extension text box, enter .mspress. Be sure to clear the Check That File Exists checkbox because this sample does not rely on a physical file. If you want, you can either limit the verbs or accept the default setting of All Verbs. For this example, I chose to limit it to GET to be a little more security conscious.

Figure 2: Use this dialog box to add application extension mapping.

Figure 2: Use this dialog box to add application extension mapping.

There you have it. Now that everything is configured, you should be able to browse to http://localhost/Scott.mspress (or use whatever name you want) and your custom HTTP hander will respond with: Hello, Scott!

 

For More Information

This month I started off with an architectural overview of HTTP handlers and discussed their benefits compared with ISAPI filters. Next I walked you through creating a simple HTTP handler. Finally, I discussed the differences between simple and custom handlers and showed you how to build and deploy a custom handler.

This article only scratches the surface of what you can do with HTTP handlers. To learn more about them, you will want to pick up a copy of Developing Microsoft ASP.NET Server Controls and Components by Nikhil Kothari and Vandana Datye.

For additional code samples, see the HTTP Handlers section of the .NET Framework Developer's Guide.

If you are new to ASP.NET, you'll want to pick up a copy of Microsoft ASP.NET Step by Step by G. Andrew Duthie. This book provides a great introduction to the technology itself and to the best practices of developing Web applications.

Also check out the following resources for information related to developing for the .NET Framework:

For a more broad overview of all the .NET technologies, you should look at David S. Platt's Introducing Microsoft .NET. It has some great information on COM Interop, Windows Forms, and .NET memory management.

 

Top of Page
 
Last Updated: Wednesday, April 2, 2003