ASP.NET 3.5核心编程学习笔记(46):HTTP模块的编写

  对于每个运行中的应用程序,ASP.NET都维护着一个HttpApplication对象的池,特定的请求会逐一由池中的实例处理。这些对象基于定义在global.asax的类创建,如果未定义global.asax,则基于HttpApplication类创建。负责处理请求的HttpApplication对象的最终目标是获取HTTP处理程序。

  在获取目标HTTP处理程序前,HttpApplication对象要使请求流经HTTP模块的管道。HTTP模块是实现IHttpModule接口的.NET Framework类,用于筛选请求的中原始数据。HTTP模块会基于每个应用程序的web.config文件进行配置,但所有ASP.NET应用程序都会继承全局的web.config文件中配置的许多系统HTTP模块。

  一般来讲,HTTP模块可以对请求进行预处理和后处理,它会监听和处理系统事件和其他模块引发的事件。ASP.NET固有的可配置特性使我们能够编写和注册自定义的HTTP模块,并将其插入到ASP.NET运行时管道中来处理系统和自定义事件。

IHttpModule接口

  IHttpModule接口定义了两个方法:Init和Dispose。Init方法用于对模块进行初始化,为处理请求做好准备。同时,我们还可以通过它来订阅所需的事件,以便得到通知。Dispose方法用于释放当前模块占用的资源(除内存外的所有资源)。我们一般在Dispose方法中关闭数据库连接或文件句柄。这两个方法的签名如下:

 
  
void Init(HttpApplication app);
void Dispose();

  下表列出了HTTP模块能够监听和处理的事件:

2011043000181841.jpg

2011043000202046.jpg

自定义的HTTP模块

  让我们编写一个相对简单的自定义模块Marker,它对当前应用程序处理的所有页面添加页眉和页脚。该类的代码如下:

 
  
using System;
using System.Web;
using System.IO;



namespace Core35.Components
{
public class MarkerModule : IHttpModule
{
#region Constants
const string PageHeaderText = " <table width=100% style='font-family:verdana;font-size:8pt;' bgcolor=cyan><tr><td align=center>You must register to continue enjoy this Web site! Click <b><a href=http://www.contoso.com>here</a>.</b></td></tr></table> " ;
const string PageFooterText = " <table width=100% style='font-family:verdana;font-size:8pt;' bgcolor=cyan><tr><td align=center>Courtesy of <b>Programming Microsoft ASP.NET 3.5</b></td></tr></table> " ;
#endregion


#region IHttpModule
public void Init(HttpApplication app)
{
// Register for pipeline events
app.BeginRequest += new EventHandler(OnBeginRequest);
app.EndRequest
+= new EventHandler(OnEndRequest);
}

public void Dispose()
{
// Nothing to do here
}
#endregion


#region Helpers
public void OnBeginRequest( object sender, EventArgs e)
{
HttpApplication app
= (HttpApplication) sender;
HttpContext ctx
= app.Context;

// More code here
if ( ! ShouldHook(ctx))
return ;

// Add custom header to the HTTP response
ctx.Response.AppendHeader( " Author " , " DinoE " );
ctx.Response.Write(PageHeaderText);
}

public void OnEndRequest( object sender, EventArgs e)
{
HttpApplication app
= (HttpApplication)sender;
HttpContext ctx
= app.Context;

// More code here
if ( ! ShouldHook(ctx))
return ;

// Append some custom text
ctx.Response.Write(PageFooterText);
}

public bool ShouldHook(HttpContext ctx)
{
return ctx.Request.Path.EndsWith( " testmarker.aspx " , StringComparison.OrdinalIgnoreCase);
}
#endregion
}
}

  OnBeginRequest添加了一个普通的页面眉和一个自定义的HTTP标头。OnEndRequest只添加页脚。

使用配置文件来注册该模块

  我们需要在web.config注册HTTP模块,以使模块生效:

 
  
< system.web >
< httpModules >
< add name = " Marker " type = " Core35.Components.MarkerModule,Core35Lib " />
</ httpModules >
</ system.web >

  模块生效的顺序取决于它们在配置列表中的物理顺序。我们可以移除某个系统模块,并替换成具有类似功能的自定义模块。在这种情况下,可以在应用程序的web.config文件中使用<remove>节点来删除默认的模块,通过<add>来插入自定义的模块。如果希望为应用程序重新定义所有HTTP模块的顺序,可使用<clear>节点,然后按意愿重新注册。

  HTTP模块只在应用程序启动时加载和初始化一次。与HTTP处理程序不同,模块会作用于所有请求。

其他HTTP模块的访问

  上例演示了如何订阅管道的事件(即由HttpApplication对象引发的事件)。那么,如果想订阅其他模块引发的事件,如何捕获呢?HttpApplication对象提供了一个名为Modubles的属性,用于获取当前应用程序中模块的集合。

  Modules的类型为HttpModuleCollection,包含应用程序中各模块的名称。该集合类继承于抽象类NameObjectCollectionBase,这个抽象类代表由字符串/对象对组成的集合。字符串指示模块的公共名称,对象是模块的实例。如要访问处理会话状态的模块:

 
  
SessionStateModule sess = app.Modules[ " Session " ];
sess.Start
+= new EventHandler(OnSessionStart);

  我们还可在global.asac文件中使用ModuleName_EventNamer的事件处理程序命名范式来处理HTTP模块引发的事件。

转载于:https://www.cnblogs.com/free722/archive/2011/04/30/2033230.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值