Summary
This article will help the users to examine the use of HTTP Modules and their use in extending the pipeline. The HTTP Pipeline is a series of extensible objects that are initiated by the ASP.NET runtime in order to process a request. Http Handlers and Http Modules are .NET components that serve as the main points of extensibility in the pipeline. This article, will demonstrate how to create an HTTP Module. Http modules are filters that can pre and post-process requests as they pass through the pipeline. As a matter of fact, many of the services provided by ASP.NET are implemented as HTTP Modules. Examples are modules which are used to implement ASP.NET security as well as ASP.NET session state.
At the most fundamental level, ASP.NET HTTP Modules are classes which implement the System.Web.IHttpModule interface, illustrated below:
public interface IHttpModule
{
void Dispose();
void Init(HttpApplication context);
}
In order to insure that your HttpHandler is hooked up to the HTTP pipeline requires an entry in the application's web config. or the machine.config file. The same holds true for HTTP modules. When an HTTP Module is added to the pipeline, the ASP.NET runtime will call the methods of the IHttpModule interface at the appropriate times. When the module is first created by the runtime, the Init method is called. As illustrated above, the parameter passed into the Init method allows your code to tie into the HttpApplication object.
The following table lists the key events exposed by the HttpApplication object. Note that all these events are implemented as multicast delegates so that numerous modules can register for each one.
Event
When It's Called
BeginRequest
Before request processing starts
AuthenticateRequest
To authenticate client
AuthorizeRequest
To perform access check
ResolveRequestCache
To get response from cache
AcquireRequestState
To load session state
PreRequestHandlerExecute
Before request sent to handler
PostRequestHandlerExecute
After request sent to handler
ReleaseRequestState
To store session state
UpdateRequestCache
To update response cache
EndRequest
After processing ends
PreSendRequestHeaders
Before buffered response headers sent
PreSendRequestContent
Before buffered response body sent
In addition to the above methods, we can also respond to the methods in the global.asax file for the HttpApplication object. These events include the session start and end events, as well as the start and end events for the application.
Let's create a simple HTTP module and hook it up to the pipeline. In the following example, the SampleModule class implements the IHttpModule interface. When the Init method is called by the runtime, the module "hooks up" to the events of the HttpApplication object. In this example, we have registered for the application's BeginRequest event as well as its EndRequest event. In our implementation of these methods, we simply record the time the request was sent in, and then we record the difference between times when the request is finished. In order to send the output to the response stream in some fashion, we add the result to the header of the HTTP response.
using System;
using System.Web;
namespace MikeModules
{
public class SampleModule : IHttpModule
{
DateTime beginrequest;
public void Init(HttpApplication app)
{
// register for events created by the pipeline
app.BeginRequest += new EventHandler(this.OnBeginRequest);
pp.EndRequest += new EventHandler(this.OnEndRequest);
}
public void Dispose() {}
public void OnBeginRequest(object o, EventArgs args)
{
// obtain the time of the current request
beginrequest = DateTime.Now;
}
public void OnEndRequest(object o, EventArgs args)
{
// get the time elapsed for the request
TimeSpan elapsedtime = DateTime.Now - beginrequest;
// get access to application object and the context object
HttpApplication app =(HttpApplication) o;
HttpContext ctx = app.Context;
// add header to HTTP response
ctx.Response.AppendHeader("ElapsedTime", elapsedtime.ToString());
}
}
}
Similar to ASP.NET HTTP Handlers, we need to notify the ASP.NET runtime that we wish to hook up our module to the pipeline. Once the module has been built and deployed to the application's bin directory or the machine's GAC, it must be registered in either the web.config file or the machine.config file. The following code adds a module to the
IIS metabase:
<httpModules>
<add type="classname, assemblyname" name="modulename"/>
<httpModules>
In order to add our module, we must implement the following code in the web.config file:
<configuration>
<system.web>
<httpModules>
<add name="TimeElapsedModule" type="SampleModules.SampleModule,SampleModules "/>
</httpModules>
</system.web>
</configuration>
In this example, the Web.config file tells the pipeline to attach an instance of the SampleModules.SimpleModule class to every HttpApplication object instantiated to service requests that target this application.
One of the most common operations when intercepting an HTTP request is to terminate the request. This is very common in custom authentication modules added to ASP.NET. In this case, the HttpApplication class has a method called CompleteRequest that is called for finishing the request. Calling CompleteRequest with the appropriate status codes can terminate the request.
ASP.NET HTTP Modules can be used to further extend the HTTP pipeline. Many of the services provided by the runtime are indeed implemented as HTTP modules. Common uses for creating custom modules include custom authentication and authorization schemes, in addition to any other filtering services that your application needs.