Click Here to Install Silverlight*
IndiaChange|All Microsoft Sites
MSDN
|Developer Centers|Library|Downloads|How To Buy|Subscribers|My MSDN
 
HTTP Handlers and HTTP Modules in ASP.NET
By Saravana Kumar
 
Article Posted: May 27, 2003

ASP.NET provides a robust framework for your Web applications. However, at times it becomes necessary to go beyond the out-of-the-box functionality.

For example, when you request a resource such as an HTML page or ASP page using the browser, IIS processes that resource based on its file extension. IIS processes ASP pages using a DLL named asp.dll. Similarly, IIS processes ASP.NET (.aspx) pages with the aspnet_isapi.dll. But sometimes you may need to process custom file extensions.

One of the goals of ASP.NET was to allow you to do everything you could potentially conceive of related to Web programming directly in the product. It shouldn't limit you. To that end, Microsoft added two new concepts: HttpModules and HttpHandlers. These did not exist inside of ASP. To find analogous functionality, you had to step outside into the world of ISAPI programming. HttpModules and HttpHandlers in ASP.NET are fairly similar to ISAPI filters, but they implement slightly different functionality.

ISAPI is an important technology that allows us to enhance the capabilities of an ISAPI-compliant Web server (IIS is an ISAPI-compliant Web server). The following components serve this purpose:

  • ISAPI Extensions
  • ISAPI Filters

ASP .NET Request Processing

ASP.NET request processing is based on a pipeline model in which ASP.NET passes http requests to all the http modules in the pipeline. Each http module receives the http request and has full control over it. The http 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.

ASP.Net Request Handling

To understand how HttpModules and HttpHandlers fit into the scheme of things, you have to understand the way that ASP.NET handles a request. When a request is received by Internet Information Server (IIS), it looks at the extension to determine which ISAPI filter should handle the request. For any of the supported file extensions, such as .aspx or .asmx, the answer is aspnet_isapi.dll. When ASP.NET fires up, it performs almost the same process again. It looks at the request and compares it to the <httpHandlers> section of the .config file. By default, machine.config maps .aspx files to the PageHandlerFactory and .asmx files to the WebServiceHandlerFactory. This mapping determines the HttpHandler (class) that is responsible for handling the request. With the concept of mapping, you can create a new HttpHandler and map it to a new type of request. In fact, this is exactly what Microsoft did with Trace.axd. You will find that it is a new HttpHandler that is registered in machine.config for any request path that ends in trace.axd.

While processing a request received from IIS, ASP.NET raises several events. They are raised in the following order:


1. BeginRequest
2. AuthenticateRequest

3. AuthorizeRequest
4. AcquireRequestState
5. ResolveRequestCache
6. Page Constructor
7. PreRequestHandlerExecute
8. Page.Init
9. Page.Load
10. PostRequestHandlerExecute
11. ReleaseRequestState
12. UpdateRequestCache
13. EndRequest
14. PreSendRequestHeaders
15. PreSendRequestContent

From a programmer's point of view, HttpHandlers and HttpModules are nothing but classes that implement certain interfaces. HttpHandlers must implement the IHttpHandler interface. Some built-in classes such as HttpApplication and Page already implement the IHttpHandler interface. Similarly, new HttpModule-derived classes must implement the IHttpModule interface. Again, the Framework contains built-in classes such as FormsAuthenticationModule and WindowsAuthenticationModule that already implement the IHttpModule interface. Both interfaces reside in the System.Web namespace.

Http Handlers

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. The interface consists of a read only property named IsReusable, which returns a Boolean value (typically true) indicating whether another request can use the IHttpHandler instance, and a ProcessRequest method, which takes a parameter of type HttpContext and performs the job of handling the extension.

I used VB.NET for the sample code, but you can use the .NET language of your choice. First, launch VS.NET, create an empty project (in the sample code), and add a new class to it. Add a reference to the System.Web namespace and add an Imports System.Web statement at the top of the class file. Add an Implements statement to add the IHttpHandler interface.

Imports System
Imports System.Web

Public Class ClsHttpHandlers
       Implements IHttpHandler
       Public ReadOnly Property IsReusable() As Booleanw

Implements System.Web.IHttpHandler.IsReusable
       Get
            Return Truet       
       End Get
   End Property

   Public Sub ProcessRequest(ByVal context As
System.Web.HttpContext) Implements
System.Web.IHttpHandler.ProcessRequests

         context.Response.Write _
            ("<html><body><h3> Your request is handled by
ClsHttpHanlders " & _
            "</h3></body></html>")
    End Sub
End Class

Configuring the HttpHandler in IIS

After you develop an HttpHandler or HttpModule you must configure IIS and ASP.NET for the new code to take effect. There are actually two steps involved in running a custom HttpHandler. First, you use the IIS Application Configuration dialog to map the file extension to the ASP.NET engine. Second, you modify the configuration sections in the application's web.config file to specify the namespace and class you want to use to handle that extension. Since we are creating a handler for handling files of a new extension, we also need to tell IIS about this extension and map it to ASP.NET. If we don't perform this step and try to access the .hand file, IIS will simply return the file rather than pass it to ASP.NET runtime. As a consequence, the HTTP handler will not be called.

For IIS, you add the required file extension in the Application Configuration dialog as shown in following figure. You can add or remove handlers using this dialog.

The dialog associates a specific file extension with a specific handler-in this case, tell IIS to use the ASP.NET engine (aspnet_isapi.dll). Following figure shows how to fill in the dialog for the example. Set the Executable field to the location of the aspnet_isapi.dll file on your server (your path may vary from the path shown in the figure). Fill in the Extension field with .hand.

Configuring the HttpHandler in Web.config

ASP.NET maintains its configuration information in the following configuration files:

  • Machine.config

  • Web.config

Machine.config file contains the configuration settings that apply to all the Web applications installed on that box. Web.config file is specific to each Web application. Each Web application can have its own web.config file. Any sub directory of a Web application may have its own web.config file; this allows them to override the settings imposed by the parent directories.

We can use <httpHandlers> and <add> nodes for adding HTTP handlers to our Web applications. In fact the handlers are listed with <add> nodes in between <httpHandlers> and </httpHandlers> nodes. Here is a generic example of adding an HTTP handler:

<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" ( *.hand in our case).

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

Next, to configure ASP.NET to recognize new handlers and modules, you modify two configuration sections in the web.config file for your application: the <httpHandlers> section, and the <httpModules>; section.

To test the sample HttpHandler you first need to create a new Web project with VS.NET. Next, open the web.config file of the new application and locate the <httpHandlers> section. ASP.NET uses the <httpHandler> section to specify mappings between file extensions and the appropriate HttpHandler. The section will already contain some handlers, for example, the following fragment shows the <httpHandlers> section on my machine :

<httpHandlers>
    <add verb="*" path="*.chart"
type="MyHttpHandler.ChartHandler,MyHttpHandler" />
    <add verb="*" path="*.vb"
type="System.Web.HttpNotFoundHandler,System.Web" />
    <add verb="*" path="*.cs"
type="System.Web.HttpNotFoundHandler,System.Web" />
    <add verb="*" path="*.vbproj"
type="System.Web.HttpNotFoundHandler,System.Web" />
    <add verb="*" path="*.csproj"
type="System.Web.HttpNotFoundHandler,System.Web" />
    <add verb="*" path="*.webinfo"
type="System.Web.HttpNotFoundHandler,System.Web" />
</httpHandlers>

For our example, you need to add httphandlers like this

<httpHandlers>
    <add verb="*" path="*.hand"
    type="HttphandlersAsm.ClsHttpHandlers,HttphandlersAsm" />
</httpHandlers>

Save your changes. Next, add a new file with the extension .hand to the Web application. Navigate to this file from your Web browser, you should see the following page.

HTTP Modules

An HTTP module is a class that contains code that executes whenever someone makes a request for a page in your ASP.NET application. Because a module executes each and every time someone makes a request for a page, modules are perfect for implementing functionality such as caching, authentication, and state management.

HTTP modules are .NET components that implement the System.Web.IHttpModule interface. These components plug themselves into the ASP.NET request processing pipeline by registering themselves for certain events. Whenever those events occur, ASP.NET invokes the interested HTTP modules so that the modules can play with the request. So you can write your http modules for the events which is mentioned already in request handling chapter.

An HTTP module is supposed to implement the following methods of the IHttpModule interface:

  • Init : This method allows an HTTP module to register its event handlers to the events in the HttpApplication object.
     
  • Dispose :This method gives HTTP module an opportunity to perform any clean up before the object gets garbage collected.

An HTTP module can register for the following events exposed by the System.Web.HttpApplication object.

BeginRequest, AuthenticateRequest, AuthorizeRequest, AcquireRequestState, ResolveRequestCache, Page Constructor, PreRequestHandlerExecute, Page.Init, Page.Load, PostRequestHandlerExecute, ReleaseRequestState, UpdateRequestCache, EndRequest , PreSendRequestHeaders, PreSendRequestContent

BeginRequest is the first event to fire when processing a request. EndRequest is almost the last event to fire. Let's write an HttpModule that sinks these events and uses them to time stamp the output HTML with the time that the request began processing and when it finished processing. This information might be useful if you were trying to profile a group of pages.

We will create this as our first HttpModule. First, we need to create a class. This class will implement the IHttpModule interface. To implement this interface, we need to supply two members: Init and Dispose. When ASP.NET loads our HttpModule to participate in processing a request, a reference to the HttpApplication object is passed to the Init method.

After we have implemented IHttpModule, we can get into doing the things that are specific to our task. In this example, we need to create event handlers for BeginRequest and EndRequest. We do this by first creating our sub procedure like this:

Public Sub SubBeginReq(ByVal s As Object, ByVal e As EventArgs)

Next we need to wire them up in the Init method that is part of the IhttpModule interface like this:

AddHandler context.BeginRequest, AddressOf SubBeginReq

The complete HttpModule is shown below:

Imports System
Imports System.Web
Imports System.Web.Caching

Public Class ClsHttpMod
       Implements IHttpModule

       ' Register Event Handlers

       Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
       AddHandler context.BeginRequest, AddressOf SubBeginReq
       AddHandler context.EndRequest, AddressOf SubEndReq

   End Sub

   Public Sub Dispose() Implements System.Web.IHttpModule.Dispose

   End Sub
   Public Sub SubBeginReq(ByVal s As Object, ByVal e As EventArgs)
   Dim app As HttpApplication
   app = CType(s, HttpApplication)
   app.Response.Write _
   ("<h4>Request Begins Here... (ClsHttpMod)</h4>")

   End Sub
   Public Sub SubEndReq(ByVal s As Object, ByVal e As EventArgs)
   Dim app As HttpApplication
   app = CType(s, HttpApplication)
   app.Response.Write _
   ("<h4>Request Ends Here...(ClsHttpMod)</h4>")

   End Sub
End Class

Registering HTTP Modules in Configuration Files

Once an HTTP module is built and copied into the bin directory of our Web application or copied into the Global Assembly Cache, then we will register it in either the web.config or machine.config file.

We can use <httpModules> and <add> nodes for adding HTTP modules to our Web applications. In fact the modules are listed by using <add> nodes in between <httpModules> and </httpModules> nodes.

Since configuration settings are inheritable, the child directories inherit configuration settings of the parent directory. As a consequence, child directories might inherit some unwanted HTTP modules as part of the parent configuration; therefore, we need a way to remove those unwanted modules. We can use the <remove> node for this.

If we want to remove all of the inherited HTTP modules from our application, we can use the <clear> node. The following is a generic example of adding an HTTP module:

<httpModules>
      <add type="classname, assemblyname" name="modulename" />
<httpModules>

The following is a generic example of removing an HTTP module from your application.

<httpModules>
      <remove name="modulename" />
<httpModules>

In the above XML,

The type attribute specifies the actual type of the HTTP module in the form of class and assembly name. The name attribute specifies the friendly name for the module. This is the name that will be used by other applications for identifying the HTTP module.

For our example , you need to add the following code:

<httpModules>
      <add type="HttpModulesAsm.ClsHttpMod,HttpModulesAsm" name="ClsHttpMod" /
</httpModules>

Save your changes. Next, add a new file with the extension .hand to the Web application. Navigate to this file from your Web browser, you should see the following page.

Using the test form, any controls or HTML markup you add to the form would appear between the two lines written by the MyBeginRequest and MyEndRequest events.

Of course, you might not want to have your HttpModule classes write output, but the example serves to show that the sample works as expected, trapping the BeginRequest and EndRequest events and processing the request .

Conclusion

As you might have realized with HTTP handlers and HTTP modules, ASP.NET has put a lot of power in the hands of developers. Plug your own components into the ASP.NET request processing pipeline and enjoy the benefits. This article should at least get you started with these components. Now you can build custom HttpHandlers to process requests with specific file extensions or to process one particular request, or create custom HttpModules to filter or manipulate requests, either before or after the ASP.NET engine processes the request.
 

 
 

©2008 Microsoft Corporation. All rights reserved. Contact Us |Terms of Use |Trademarks |Privacy Statement
Microsoft