如何:创建自定义 HTTP 模块
HTTP 模块介绍
HTTP 模块是一个在每次针对应用程序发出请求时调用的程序集。HTTP 模块作为 ASP.NET 请求管线的一部分调用,它们能够在整个请求过程中访问寿命周期事件。因此,HTTP 模块使您有机会检查传入的请求并根据该请求采取操作。它们还使您有机会检查出站响应并修改它。
ASP.NET HTTP 模块针对所有的请求运行,这与 ISAPI 筛选器类似。但是它们是用托管代码编写的,而且可以与 ASP.NET 应用程序的生命周期完全集成。
HTTP 模块典型的用法包括:
-
安全性。因为您可以检查传入的请求,所以 HTTP 模块可以在请求页、XML Web services 或调用处理程序之前执行自定义的身份验证或其他安全检查。
-
统计信息和日志记录。因为 HTTP 模块是在每次请求时调用的,所以,您可以将请求统计信息和日志记录信息收集到一个集中的模块中,而不是收集到各页中。
-
自定义的页眉或页脚。因为您可以修改出站响应,所以可以在每一个页面或 XML Web services 响应中注入内容,如自定义的标头信息。
ASP.NET 使用模块来实现各个应用程序功能,包括 Forms 身份验证、缓存、会话状态和客户端脚本服务。在每种情况下,如果这些服务处于启用状态,模块会作为请求的一部分调用,并执行在任何单一页请求范围之外的任 务。模块可以使用应用程序事件,可能会引发可在 Global.asax 文件中处理的事件。有关应用程序事件的更多信息,请参见 ASP.NET 应用程序生命周期概述。
注意 |
|---|
|
HTTP 模块不同于 HTTP 处理程序。对于所有的请求和响应都可调用 HTTP 模块,而 HTTP 处理程序仅在响应特定的请求时才运行。有关更多信息,请参见 HTTP 处理程序介绍。 |
HTTP 模块的工作方式
在应用程序的 Web.config 文件中注册自定义的 HTTP 模块。当 ASP.NET 创建表示您的应用程序的 HttpApplication 类的实例时,将创建已注册的任何模块的实例。在创建模块时,将调用它的 Init 方法,并且模块会自行初始化。有关更多信息,请参见 ASP.NET 应用程序生命周期概述。
在模块的 Init 方法内,可以订阅各种应用程序事件(如 BeginRequest 或 EndRequest),这可以通过将事件绑定到模块中已创建的方法来完成。当这些事件被引发时,会调用模块中适当的方法,并且模块可以执行所需的任何逻辑,如身份验证检查或记录请求信息。在事件处理过程中,模块能够访问当前请求的 Context 属性。这使您可以将请求重定向到其他页、修改请求或者执行任何其他请求操作。例如,如果您的模块中包括身份验证检查,则模块可能会检查凭据,如果凭据不正 确的话,会重定向到登录页或错误页。否则,当模块的事件处理程序完成运行时,ASP.NET 会调用管线中的下一个进程,这可能是另一个模块,也可能是用于该请求的 HTTP 处理程序(如 .aspx 文件)。
HTTP 模块与 Global.asax 文件
可 以在应用程序的 Global.asax 文件中实现模块的许多功能,这使您可以响应应用程序事件。但是,模块相对于 Global.asax 文件具有如下优点:模块可以进行封装,因此可以在创建一次后在许多不同的应用程序中使用。通过将它们添加到全局程序集缓存 (GAC) 并将它们注册到 Machine.config 文件中,可以跨应用程序重新使用它们。有关更多信息,请参见全局程序集缓存。
但是,使用 Global.asax 文件有一个好处,那就是您可以将代码放在其他已注册的模块事件(如 Session_Start 和 Session_End 方法)中。此外,Global.asax 文件还允许您实例化可在整个应用程序中使用的全局对象。
当您需要创建依赖应用程序事件的代码并且希望在其他应用程序中重用模块时,或者不希望将复杂代码放在 Global.asax 文件中时,应当使用模块。当您需要创建依赖应用程序事件的代码但不需要跨应用程序重用它时,或者需要订阅不可用于模块的事件(如 Session_Start)时,应当将代码放在 Global.asax 文件中。
创建 HTTP 模块
可以通过以下方法来创建自定义的 HTTP 模块:创建一个实现 IHttpModule 接口的类,然后在 Web.config 文件中注册该类。编写 HTTP 模块的一般过程为:
-
创建一个实现 IHttpModulefrlrfSystemWebIHttpModuleClassTopic 接口的类。
-
为 InitfrlrfSystemWebIHttpModuleClassInitTopic 方法编写一个处理程序。init 方法应该初始化模块并订阅所需的任何应用程序事件。例如,如果您希望向响应中追加内容,则可以订阅 EndRequest 事件,或者如果您希望执行自定义的身份验证逻辑,则可以订阅 AuthenticateRequest 事件。有关应用程序事件的更多信息,请参见 ASP.NET 应用程序生命周期概述。
-
为已经订阅的事件编写代码。
-
如果模块需要清理,还可选择实现 Dispose 方法。
-
在 Web.config 文件中注册模块。
有关更多信息,请参见如何:创建自定义 HTTP 模块。
如何:创建自定义 HTTP 模块
本主题中描述的自定义 HTTP 模块阐释了 HTTP 模块的基本功能。在响应下面两个事件时调用该模块:BeginRequest 事件和 EndRequest 事件。这使该模块可以在处理页请求之前和之后运行。在这种情况下,该模块向请求的 ASP.NET 网页的任一 HTTP 请求开头处添加一条消息,并在处理请求后添加另一条消息。
注意 |
|---|
|
BeginRequest 和 EndRequest 事件只是在处理页期间发生的两个事件。有关在处理页期间引发的事件的更多信息,请参见 ASP.NET 网页中的服务器事件处理。 |
每个事件处理程序都编写为模块的私有方法。在引发已注册事件时,ASP.NET 调用该模块中适当的处理程序方法,该方法将信息写入 ASP.NET 网页中。
创建自定义 HTTP 模块类
-
如果网站还没有 App_Code 文件夹,请在该站点的根目录下创建这样的一个文件夹。
-
在 App_Code 目录中,创建一个名为 HelloWorldModule.vb(对于 Visual Basic)或名为 HelloWorldModule.cs(对于 C#)的类文件。
注意 |
|---|
|
或者,可以将 HelloWorldModule 类编译到一个库中,并将得到的 .dll 文件放在 Web 应用程序的 Bin 目录中。 |
-
将以下代码添加到该类文件中:
Imports Microsoft.VisualBasic Public Class HelloWorldModule Implements IHttpModule Public ReadOnly Property ModuleName() As [String] Get Return "HelloWorldModule" End Get End Property ' In the Init function, register for HttpApplication ' events by adding your handlers. Public Sub Init(ByVal application As HttpApplication) _ Implements IHttpModule.Init AddHandler application.BeginRequest, _ AddressOf Me.Application_BeginRequest AddHandler application.EndRequest, _ AddressOf Me.Application_EndRequest End Sub Private Sub Application_BeginRequest(ByVal source As Object, _ ByVal e As EventArgs) ' Create HttpApplication and HttpContext objects to access ' request and response properties. Dim application As HttpApplication = CType(source, _ HttpApplication) Dim context As HttpContext = application.Context context.Response.Write _ ("<h1><font color=red>HelloWorldModule: " & _ "Beginning of Request</font></h1><hr>") End Sub Private Sub Application_EndRequest(ByVal source As Object, _ ByVal e As EventArgs) Dim application As HttpApplication = CType(source, _ HttpApplication) Dim context As HttpContext = application.Context context.Response.Write _ ("<hr><h1><font color=red>HelloWorldModule: " & _ "End of Request</font></h1>") End Sub Public Sub Dispose() Implements IHttpModule.Dispose End Sub End Class
public class HelloWorldModule : IHttpModule { public HelloWorldModule() { } public String ModuleName { get { return "HelloWorldModule"; } } // In the Init function, register for HttpApplication // events by adding your handlers. public void Init(HttpApplication application) { application.BeginRequest += (new EventHandler(this.Application_BeginRequest)); application.EndRequest += (new EventHandler(this.Application_EndRequest)); } private void Application_BeginRequest(Object source, EventArgs e) { // Create HttpApplication and HttpContext objects to access // request and response properties. HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("<h1><font color=red> HelloWorldModule: Beginning of Request </font></h1><hr>"); } private void Application_EndRequest(Object source, EventArgs e) { HttpApplication application = (HttpApplication)source; HttpContext context = application.Context; context.Response.Write("<hr><h1><font color=red> HelloWorldModule: End of Request</font></h1>"); } public void Dispose() { } }
注册 HTTP 模块
在创建完 HelloWorldModule 类后,可以通过在 Web.config 文件中创建一项来注册该模块。
在 Web.config 文件中注册该模块
-
如果网站还没有 Web.config 文件,请在该站点的根目录下创建一个这样的文件。
-
将下面突出显示的代码添加到该 Web.config 文件中:
<configuration> <system.web> <httpModules> <add name="HelloWorldModule" type="HelloWorldModule"/> </httpModules> </system.web> </configuration>这段代码用 HelloWorldModule 的类名和模块名注册该模块。
测试自定义 HTTP 模块
创建并注册完自定义 HTTP 模块后,可以对它进行测试。
测试自定义 HTTP 模块
-
在应用程序中创建一个 Default.aspx 页。
-
在浏览器中请求该 Default.aspx 页。
HTTP 模块会将一个字符串追加到响应的开头和结尾。在请求扩展名指定为 ASP.NET 类型的文件时,该模块将会自动运行。有关更多信息,请参见 HTTP 模块介绍。

注意
浙公网安备 33010602011771号