Like in other .NET-applications, exception-handling is also available
in ASP.NET-applications. There are a few extensions and special
features for exception-handling in ASP.NET that will be explained in
this article: Predefined IHttpModules allow you to process incoming requests and outgoing
responses to and from an ASP.NET application. This article offers a
closer look at using HTTP modules in ASP.NET applications.
Introduction to HTTP modules
ASP.NET HTTP modules provide access to incoming and outgoing traffic
to a Web application. They are similar to Internet Server Application
Programming Interface (ISAPI) filters in that they run for all
requests, but HTTP modules are written in managed code and are fully
integrated with the lifecycle of an ASP.NET application.
HTTP modules provide pluggable functionality to ASP.NET
applications. These modules are added to the request pipeline before
and after the ASP.NET HTTP handler fires. HTTP modules are different
than HTTP handlers. HTTP modules are called for all requests and
responses, whereas HTTP handlers run only in response to specific
requests.
HTTP modules and the Global.asax file available in all ASP.NET
applications provide the same functionality, but the implementation is
a bit different. The Global.asax file requires code in the application,
thus compilation when it changes; HTTP modules are completely separate.
A great aspect of HTTP modules is that they are built without
affecting existing applications — albeit the extensible architecture.
These are easily added or removed to and from an ASP.NET application
via the Web configuration (web.config) file.
Some common uses of HTTP modules include the following:
- Headers: You can easily inject custom header information into each page.
- Logging: You can easily gather logging or
statistical data for every request. The creation of a custom HTTP
module provides a central location for logging as opposed to code in
every page.
- Security: You can perform custom authentication or
security checks on each page request. You may filter based upon user
credentials, IP address, etc. The ASP.NET MemeberShip Provider work in this style.
How HTTP modules work
HTTP modules are registered in the web.config file. This ties the
module to an application. As a result, when ASP.NET creates an instance
of the HttpApplication class for an application, instances of any
modules that have been registered are created as well. The module’s
Init method is called when it is instantiated.
Within the Init method, the module subscribes to one or more events
from the HttpApplication object. These events correspond to user
actions within an ASP.NET application. These events include the
following:
- AcquireRequestState: This is the event you call to acquire or create the state for the request.
- AuthenticateRequest: This event fires when a security module needs to authenticate the user before it processes the request.
- AuthorizeRequest: This event is fired by a security module when the request needs to be authorized after authentication.
- BeginRequest: This event signals that a new request is beginning.
- Disposed: This event signals the application is ending, so it allows the module to perform clean up operations.
- EndRequest: This event signals that the request is ending.
- Error: This event is called when an error occurs during request processing.
- PostRequestHandlerExecute: This event signals that the handler has finished processing the request.
- PreRequestHandlerExecute: This event signals that the handler for the request is about to be called.
- PreSendRequestContent: This event signals that content is about to be sent to the client.
- PreSendRequestHeaders: This event signals that HTTP headers are about to be sent to the client.
- ReleaseRequestState: This event signals that the handler has finished processing the request.
- ResolveRequestCache: This event is triggered after authentication.
- UpdateRequestCache: This event fires after a response from the handler.
An HTTP module may use any of these events.
Creating an HTTP module
You build a custom HTTP module using the IHttpModule interface,
which you can find in the System.Web namespace. You want to possiblity to handle errors is in an own IHttpModule. To define it, you have to implement the interface IHttpModule and bind your error-handler in this class:
public void Init(HttpApplication app);
public void Dispose();
The Init method is important since it is called when the HTTP module
is called to process incoming requests or outgoing responses. Calls to
events (from the previous list) are placed in this method. If one of
the events from the HttpApplication class is used, the code to handle
the event must be included as well. This includes a delegate, the
method, hooking to the event, and so forth.
Once a module is built, it may be registered by way of the
httpModules section of the web.config file as the following snippet
illustrates:
<system.web>
<httpModules>
<add type="[Class], [Assembly]" name="[ModuleName]" />
<remove type="[Class], [Assembly]" name="[ModuleName]" />
<clear />
</httpModules>
The best way to grasp the use of HTTP modules is to build one. HTTP
modules are created as a class library. When using Visual Studio, a
reference to the System.Web namespace is added to the project to access
the required classes.
The following C# sample demonstrates a simple HTTP module that
is tied to the BeginRequest and EndRequest events for a user request.
The code displays a simple message in the browser stating the event
fired. The events are registered in the module’s Init method with a
method created for each event handled.
public class ErrorModule : IHttpModule
{
public ErrorModule()
{
}
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.Error += new EventHandler(context_Error);
}
void context_Error(object sender, EventArgs e)
{
Exception e = HttpContext.Current.Server.GetLastError();
// Clear the error so that it doesn't occur again in
// the Application_Error-handler
HttpContext.Current.Server.ClearError();
HttpContext.Current.Response.Redirect("ErrorPage.htm");
}
#endregion
}
So what is the benefit of using an own HttpModule. Well, the name
already says it: You have a modularization for your error-handling. You
can change your implementa
tion at one place without touching your
application-logic and you can change the errorhandling of your
appliation by defining another HttpModule and configuring it in your
web.app..