HTTP Handlers and Modules in ASP.NET
Understanding HTTP Handlers and Modules is crucial for comprehending how ASP.NET processes incoming HTTP requests and generates responses. These two components work at different stages of the request pipeline, providing powerful extensibility points.
HTTP Handlers
An HTTP Handler is responsible for processing a specific type of HTTP request and generating the output that is sent back to the client. Think of them as the "final destination" for a particular request URL pattern. Each request is ultimately handled by a specific HTTP Handler.
Examples of HTTP Handlers:
.aspx
pages are handled bySystem.Web.UI.Page
..asmx
web services are handled bySystem.Web.Services.Protocols.WebServiceHandler
.- Static files (like
.html
,.css
,.js
) are typically handled bySystem.Web.StaticFileHandler
.
Implementing a Custom HTTP Handler
You can create your own custom HTTP handlers by implementing the IHttpHandler
interface. This interface requires you to implement two methods:
ProcessRequest(HttpContext context)
: This is where the core logic for handling the request resides.IsReusable
: A boolean property indicating if the handler can be reused across multiple requests.
Here's a simple example:
using System;
using System.Web;
public class MyCustomHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello from MyCustomHandler!");
}
public bool IsReusable
{
get { return true; }
}
}
To make ASP.NET use this handler, you'd register it in your web.config
file:
<configuration>
<system.web>
<httpHandlers>
<add path="myhandler.txt" verb="*" type="MyCustomHandler, YourAssembly"/>
</httpHandlers>
</system.web>
</configuration>
HTTP Modules
HTTP Modules (also known as HTTP Modules or Pipeline Modules) hook into the ASP.NET request-processing pipeline at various stages. Unlike handlers that deal with the final processing of a request, modules can intercept requests and responses at multiple points, allowing them to perform actions like authentication, logging, modifying headers, or even short-circuiting the request processing.
Every ASP.NET application has a set of built-in HTTP modules, such as the Forms Authentication module, the Session State module, and the URL Authorization module. These modules are automatically registered and enabled.
Implementing a Custom HTTP Module
To create a custom HTTP module, you need to implement the IHttpModule
interface. This interface requires one method:
Init(HttpApplication context)
: This method is called when the HTTP module is initialized, and it's where you register event handlers for various stages of the HTTP pipeline.Dispose()
: This method is called when the application is shutting down, allowing you to clean up resources.
The Init
method is where the magic happens. You subscribe to events exposed by the HttpApplication
object, which represent different stages of the request pipeline. Common events include:
BeginRequest
: Fired at the beginning of a request.AuthenticateRequest
: Fired when authentication is performed.AuthorizeRequest
: Fired when authorization is performed.PostRequestHandlerExecute
: Fired after the handler has finished executing.EndRequest
: Fired at the end of a request.
Example of a custom HTTP Module:
using System;
using System.Web;
public class MyLoggingModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OnBeginRequest;
context.EndRequest += OnEndRequest;
}
private void OnBeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Items["StartTime"] = DateTime.Now;
System.Diagnostics.Trace.WriteLine("Request started: " + HttpContext.Current.Request.Url);
}
private void OnEndRequest(object sender, EventArgs e)
{
DateTime startTime = (DateTime)HttpContext.Current.Items["StartTime"];
TimeSpan duration = DateTime.Now - startTime;
System.Diagnostics.Trace.WriteLine("Request ended. Duration: " + duration.TotalMilliseconds + "ms");
}
public void Dispose()
{
// Clean up any resources here if needed
}
}
To register this module, you add it to the <httpModules>
section (for ASP.NET 2.0 and later) or <modules>
within <system.webServer>
(for IIS 7 integrated pipeline):
<configuration>
<system.web>
<httpModules>
<add name="MyLoggingModule" type="MyLoggingModule, YourAssembly"/>
</httpModules>
</system.web>
<system.webServer>
<modules>
<add name="MyLoggingModule" type="MyLoggingModule, YourAssembly"/>
</modules>
</system.webServer>
</configuration>
<system.webServer>/<modules>
configuration is the preferred approach for IIS 7+ with the integrated pipeline.
Key Differences and Relationship
- Purpose: Handlers process specific requests, while modules intercept and act on requests and responses throughout the pipeline.
- Scope: A request is ultimately handled by one handler. A request can pass through multiple modules.
- Execution: Handlers execute later in the pipeline, closer to response generation. Modules can execute at various stages.
Modules can also influence which handler is ultimately selected or even stop the request processing before it reaches a handler.
Advanced Scenarios
HTTP Handlers and Modules are fundamental to building sophisticated web applications and extending ASP.NET's functionality. They are used extensively in:
- Implementing custom authentication and authorization schemes.
- Performing request validation and sanitization.
- Implementing caching strategies.
- Compressing or transforming response content.
- Integrating with third-party services.
By leveraging these extensibility points, developers can create highly customized and efficient web applications.