Handler Tutorial

Handler Concept in ASP.NET

Some ASP.NET files are dynamically generated. They are generated with C# code or disk resources. These files do not require web forms. Instead, an ASHX generic handler is ideal. It can dynamically return an image from a query string, write XML, or any other data.

HTTP handlers are the .NET components that implement the System.Web.IHttpHandler interface. Any class that implements the IHttpHandler interface can act as a target for the incoming HTTP requests. HTTP handlers are somewhat similar to ISAPI extensions. One difference between HTTP handlers and ISAPI extensions is that HTTP handlers can be called directly by using their file name in the URL, similar to ISAPI extensions.

HTTP handlers implement the following methods.

Method Name Description
ProcessRequest This method is actually the heart of all http handlers. This method is called to process http requests.
IsReusable This property is called to determine whether this instance of http handler can be reused for fulfilling another requests of the same type. HTTP handlers can return either true or false in order to specify whether they can be reused.

These classes can be mapped to http requests by using the web.config or machine.config file. Once that is done, ASP.NET will instantiate http handler whenever the corresponding request comes in. We will see how to specify all of these details in web.config and/or machine.config files.

ASP.NET also supports the creation of http handlers by means of the IHttpHandlerFactory interface. ASP.NET provides the capability of routing http requests to an object of the class that implements the IHttpHandlerFactory interface. Here, ASP.NET utilizes the Factory design pattern. This pattern provides an interface for creating families of related objects without specifying their concrete classes. In simple terms, you can consider such a class as a factory that creates http handler objects depending on the parameters passed to it. We don’t have to specify a particular http handler class to instantiate; http handler factory takes care of it. The benefit of this is if in the future the implementation of the object that implements the IHttpHandler interface changes, the consuming client is not affected as long as the interface remains the same.

These are following methods in IHttpHandlerFactory interface:

Method Name Description
GetHandler This method is responsible for creating the appropriate handler and returns the reference out to the calling code (the ASP.NET runtime). Handler object returned by this method should implement the IHttpHandler interface.
ReleaseHandler This method is responsible for releasing the http handler once request processing is complete. The implementation of the factory decides what it should do. Factory implementation can either actually destroy the instance or return it to a pool for future requests.

Introduction

First, we review the goal in using ASHX files in the ASP.NET web development framework. 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://www.dotnetperls.com/?file=name

This part lists the steps you can take to add a new ASHX file. To do this, 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 called Handler.ashx.

ASP.NET Request Processing

ASP.NET request processing is based on a pipeline model in which ASP.NET passes http requests to all the modules in the pipeline. Each module receives the http request and has full control over it. The module can play with the request in any way it sees fit. Once the request passes through all of the HTTP modules, it is eventually served by an HTTP handler. The HTTP handler performs some processing on it, and the result again passes through the HTTP modules in the pipeline.

The following figure describes this flow.

Notice that during the processing of an http request, only one HTTP handler will be called, whereas more than one HTTP modules can be called.

Autogenerated code

Here we note what the autogenerated code in the ASHX file does. 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. You shouldn’t modify the interface inheritance or remove either of the members.

URL Mappings

It is often desirable to map an older URL or path to your new ASHX file. 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; alternatively, you can use more complex RewritePath methods.

Part of Web.config file [XML]

<system.web>

    <urlMappings enabled=”true”>

               <add url=”~/Default.aspx” mappedUrl=”~/Handler.ashx”/>

    </urlMappings>

URL mappings.

The above Web.config markup will automatically link one URL to another. 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.

Add example image

Here we mention what you can do with the ASHX file involving images. 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.

Modify 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.

ASHX code-behind file [C#]

<%@ 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;

               }

    }

}

Test handler

Here we test the new configuration and ASHX file on the local machine. 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.

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 the C# language. 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.

ASHX modified code-behind [C#]

<%@ 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. The strings it returns are shown next here.

URL = http://www.dotnetperls.com/?file=logo

File query string: logo

     File written: Logo1.png

URL = http://www.dotnetperls.com/?file=flower

File query string: flower

     File written: Flower1.png

Test 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.

Uses

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.

Performance

You are likely wondering if there is any performance advantage or change to using ASHX files. ASHX files are less complex and they do not involve as many events. As you can imagine firing more than ten events each time a request is handled is a fair amount more expensive than only firing one event. Therefore, there will be some performance advantage to using ASHX files where possible.

Choose handlers

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…

  • If you have simple HTML pages
  • ASP.NET custom controls
  • Simple dynamic pages

Use handlers…

  • If you have binary files
  • Dynamic image views
  • Performance-critical web pages
  • XML files
  • Minimal web pages
  • Apply security mechanism
  • URL rewriting
  • Filter something in the request that is send to IIS

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, or XML and other non-HTML web pages.
it’s usually much more convenient to generate a simple handler than it is to create a whole new assembly to handle the request. Second, you don’t need to run interference with either Web.Config or with IIS. That is, Web.Config and IIS already understand what to do about files with the extension of .ashx. Installing ASP.NET places those when mapping into IIS.

Registering Handler in Web.Config

The following is a generic example of adding an HTTP module:

<httpHandlers>

            <add verb=”supported http verbs” path=”path” type=”namespace.classname, assemblyname” />

<httpHandlers>

In the above XML,

  • The verb attribute specifies the HTTP verbs supported by the handler. If the handler supports all of the HTTP verbs, simply use “*”, otherwise list the supported verbs in a comma separated list. So if your handler supports only HTTP GET and POST, then verb attribute will be “GET, POST”.
  • The path attribute specifies the path or wildcard specification of the files for which this handler will be invoked. For example, if you want your handler to be called only when test.xyz file is requested, then the path attribute will contain “test.xyz”; similarly if you want your handler called for any file having .xyz extension, the path attribute will contain “*.xyz”.
  • The type attribute specifies the actual type of the handler or handler factory in the form of a combination of namespace, class name and assembly name. ASP.NET runtime first searches the assembly DLL in the application’s bin directory and then searches in the Global Assembly Cache (GAC).

Conclusion

Using HttpHandlers as server-side proxies turns out to be a simple way to solve the pesky cross-domain restrictions that we’ve all run into from time to time. All said and done, using an HttpHandler to proxy third-party requests takes few lines of code, but offers nearly unlimited flexibility.

In addition to the obvious benefit of getting around the cross-domain restriction, bouncing requests through your own server potentially has a range of other benefits, including:

  • Error handling – This approach not only passes unhandled exceptions on the WebClient request back through to the client-side, but it also gives you the ability to enhance the error handling with your own sanity checks and constraints.
  • Caching – As shown in this post’s final example, you can very easily interject your own caching layer for requests passing through the HttpHandler proxy. That’s especially useful when working against rate limited or potentially slow/flaky APIs (like Twitter’s).
  • Security – When you’re accustomed to server-side programming, the revealing nature of client-side JavaScript can be unnerving. Learning to appropriately partition sensitive algorithms and data between client and server is key to mitigating that issue. Along those lines, moving the remote request to code running on your server is one way to keep sensitive information like API keys and passwords safely hidden from view-source and client-side developer tools.
  • Reliability – One of JSONP’s less obvious drawbacks is the fact that it relies on injecting a third-party script. However, your users may be using something like No Script to purposely block third-party scripts, effectively shutting down your ability to use JSONP. Even if you prefer JSONP in most cases, a local server-side proxy can be helpful as a fallback in case of unexpected JSONP failures.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s