Dot Net Perls

Custom ASHX Handler Tutorial - ASP.NET

by Sam Allen

Problem

You want to create an ASP.NET file that is not a typical web forms page. Your file will need to dynamically return an image from a query string. You also need to have a way to return XML or other non-HTML web pages.

Solution: ASP.NET and C#

Here is a simple tutorial for using an ASHX generic handler in ASP.NET. What we will be able to do is use the ASHX file in a URL, and have it return content dynamically. We will use the query string, and the final URLs will look like this:

http://dotnetperls.com/?file=name

Getting started

First, open your ASP.NET web site. Go to the Website menu and click on the very first menu item there, "Add New Item...". This will present the Add New Item dialog box. Select the Generic Handler item, and you will get a new file with some code in it.

What does the code there do?

It defines two parts of the IHttpHandler interface. The important part is ProcessRequest(), which will be invoked whenever the Handler.ashx file is requested or pointed to.

1. Map the handler

For backwards compatibility and for search engine optimization, you will probably want the new handler to take over an old URL in your site. To do this, use urlMappings. [urlMappings for Redirects - dotnetperls.com]

<system.web>
    <urlMappings enabled="true">
        <add url="~/Default.aspx" mappedUrl="~/Handler.ashx"/>
    </urlMappings>
    ...

URL mappings. Now, when the Default.aspx page is requested, your Handler.ashx file will take over. This means you can map the default page in a directory to your handler.

2. Add example image to project

Find your favorite image on your disk or on the Internet and add it to your website project. For my example, the image I chose was Flower1.png. Next we will use this image in the Handler.ashx file.

3. Modify your Handler.ashx

Your handler has two parts, and here we must modify the ProcessRequest() method. We can change the ContentType of the file and the Response content. Modify your Handler.ashx to be similar to the following, with your image ContentType and file name.

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

using System;
using System.Web;

public class Handler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {
        // Comment out these lines first:
        // context.Response.ContentType = "text/plain";
        // context.Response.Write("Hello World");

        context.Response.ContentType = "image/png";
        context.Response.WriteFile("~/Flower1.png");
    }

    public bool IsReusable {
        get {
            return false;
        }
    }
}

4. Test the handler

Now click the green arrow to run your website on the development server. You should see the image in your browser. This is the result of writing the image to the response in the handler.

5. Add functionality

The example here so far is relatively useless. All it does is allow us to pipe an image through an ASHX handler. Note that you can add any logging code or referrer logic to the handler in C#.

Using query strings. Developers commonly need to use the QueryString collection on the Request. You can use the Request.QueryString in the Handler just like you would on any ASPX web form page.

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

using System;
using System.Web;

public class Handler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {

        HttpResponse r = context.Response;
        r.ContentType = "image/png";
        //
        // Write the requested image
        //
        string file = context.Request.QueryString["file"];
        if (file == "logo")
        {
            r.WriteFile("Logo1.png");
        }
        else
        {
            r.WriteFile("Flower1.png");
        }
    }

    public bool IsReusable {
        get {
            return false;
        }
    }
}

What this does. The above code receives requests and then returns a different file based on the QueryString collection value. It will return one of two images from the two query strings.

URLFile query stringFile written
http://dotnetperls.com/?file=logologoLogo1.png
http://dotnetperls.com/?file=flowerflowerFlower1.png

6. Test the query string

Does all this really work? Yes, it does, but it is always important to test it. Open your browser and on the path add query strings like shown in the above table. What happens is that ASP.NET internally maps the Default.aspx page to your Handler.ashx. Then, it receives the query string and write the appropriate file.

Where can I use this code?

The code here could be used as a hit tracker that counts visitors and logs referrers. This could provide a more accurate visit count than server logs (because of browser and bot differences).

Handlers vs. web pages. ASP.NET web forms inherit from the Page class. This provides them with many events and a very detailed initialization and event model. You don't need that for dynamic images, XML, or binary files.

Is it fast?

Yes. Here I point to Robbe Morris' benchmarking work, where he found that generic handlers are 5-10% faster than ASPX web forms that do the exact same operations-- even without server controls. [Use Custom Http Handlers To Improve Performance in ASP.NET - eggheadcafe.com]

Why is it faster? It is faster because it does a lot less. As you can imagine firing 10+ events each time a request is handled is a fair amount more expensive than only firing one event.

Which should I use?

Here I want to propose some guidelines about when to use custom handlers and when to use ASPX web form pages. Handlers are better for binary data, and web forms are best for rapid development.

Use web forms (ASPX)
when you have...
Use handlers (ASHX)
when you have...
• Simple HTML pages
• ASP.NET custom controls
• Simple dynamic pages
• Binary files
• Dynamic image views
• Performance-critical web pages
• XML files
• Minimal web pages

Control trees

Use custom handlers when you do not require the custom control tree or the whole HTML web form framework. This will result in greater performance and much simpler code to debug.

What does IsReusable do?

I don't know precisely, although my reading indicates that it can improve performance and decrease memory pressure by not destroying the handler repeatedly. I hope to write more on when you can set it to true. [C# - Garbage Collection Visualizations - dotnetperls.com]

Summary

What I showed here could be modified to fill in many different important web site functions. Combine urlMappings with query strings on custom handlers to greatly simplify and streamline your back-end web site code.

Does it really work? The ASHX approach works well and if you are reading this page, it must be working at least well enough to serve the article. Speaking of articles, there are many more related ones at this site.

Dot Net Perls
About
Sitemap
Source code
RSS
ASP.NET
Page Load Event and AJAX
Custom ASHX Handler Tutorial
Cache Examples and Overview
System.Timers for ASP.NET Website Tutorial
HtmlTextWriter Use
Recent
Pi
NGEN Installer Class
List Element Equality
DateTime Tips and Tricks
Remove HTML Tags From String
© 2008 Sam Allen. All rights reserved.