ASP.NET-自定义HttpModule与HttpHandler
2020-12-13 06:01
标签:style blog class c code tar
在之前的ASP.NET是如何在IIS下工作的这篇文章中介绍了ASP.NET与IIS配合工作的机制,在http请求经过一系列处理后,最后到达ASP.NET管道中,这时,就是Http
Modules和HttpHandler出场的时候了。 再来摆出管道工作时序图来一看:
HttpModule HttpModule是类似于过滤器的作用,可以没有,也可以有任意个,每一个都可以订阅管道事件中的任意个事件,在每个订阅的事件中可自定义功能实现。 HttpModule是实现IHttpModule接口的类。接口如下: 下面实现一个HttpModule,并订阅管道中的一系列事件,订阅事件就是在Init方法中绑定EventHandler的过程: 代码有点长,因为我把每一个事件都订阅了,这样一来可以清楚的看出哪些事件执行了,这些事件执行的先后顺序是什么。代码如下: 订阅的事件实现中,将事件名称保存到我本地D盘的一个文本文件中。 代码实现完毕了,下一步就是要代码起作用了,很简单,只需要在web.config中简单配置就可以了。配置中注意IIS7集成模式和IIS7经典模式(包括IIS6)的区别,配置如下: 如此一来,一个HttpModule及其配置工作就完成了,接下来,发布网站到IIS或者直接在VS中运行,随便访问项目中的一个文件(任何文件类型都可以),我的项目中有一个WebForm2.aspx的页面,我在浏览器中访问这个页面,发现页面是空白的,因为页面中我什么都没写,上面的Module实现中,我把输出全部放到本地D盘的一个文本文件中了,ok,打开那个文本文件。如图: 我们看到输出内容,第2行是访问的页面地址,下面依次为订阅的事件输出,我们清楚的看到了事件的执行顺序。 访问一个页面的过程中,依次触发了23个事件,而HttpModule可订阅的事件个数为25个,观察发现,Error和Disposed这两个事件没有触发。Error事件在发生错误的情况下执行,而Disposed事件,当我们关闭刚才打开的页面,再到文本文件里查看,发现Disposed事件出现了,所以Disposed在会话结束后触发。 由于HttpModule的个数可以有多个,我们可以按照上面的方式定义HttpModule实现类,然后再web.config中增加配置项,就可以实现多个HttpModule同时订阅管道事件了。 介绍完HttpModule,那么HttpHandler又是什么呢,它又在什么什么时候执行呢?接下来看一下HttpHandler。 HttpHandler HttpHandler是HTTP请求的处理中心,真正地对客户端请求的服务器页面做出编译和执行,并将处理过后的信息附加在HTTP请求信息流中再次返回到HttpModule中。
HttpHandler是实IHttpHandler接口的类,IHttpHandler接口定义如下: 接口中只有一个属性和一个方法,所以实现一个HttpHandler也很简单,下面实现一个简单的HttpHandler,代码如下:
public interface IHttpModule
{
// 摘要:
// 处置由实现 System.Web.IHttpModule 的模块使用的资源(内存除外)。
void Dispose();
//
// 摘要:
// 初始化模块,并使其为处理请求做好准备。
//
// 参数:
// context:
// 一个 System.Web.HttpApplication,它提供对 ASP.NET 应用程序内所有应用程序对象的公用的方法、属性和事件的访问
void Init(HttpApplication context);
}
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
");
"); public class MyModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
//此处放置清除代码。
}
public void Init(HttpApplication context)
{
// 下面是如何处理 LogRequest 事件并为其
// 提供自定义日志记录实现的示例
context.LogRequest += new EventHandler(OnLogRequest);
context.BeginRequest += new EventHandler(context_BeginRequest);
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
context.AuthorizeRequest += new EventHandler(context_AuthorizeRequest);
context.Disposed += new EventHandler(context_Disposed);
context.Error += new EventHandler(context_Error);
context.EndRequest += new EventHandler(context_EndRequest);
context.MapRequestHandler += new EventHandler(context_MapRequestHandler);
context.PostAcquireRequestState += new EventHandler(context_PostAcquireRequestState);
context.PostAuthenticateRequest += new EventHandler(context_PostAuthenticateRequest);
context.PostAuthorizeRequest += new EventHandler(context_PostAuthorizeRequest);
context.PostLogRequest += new EventHandler(context_PostLogRequest);
context.PostReleaseRequestState += new EventHandler(context_PostReleaseRequestState);
context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
context.PostResolveRequestCache += new EventHandler(context_PostResolveRequestCache);
context.PostUpdateRequestCache += new EventHandler(context_PostUpdateRequestCache);
context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
context.RequestCompleted += new EventHandler(context_RequestCompleted);
context.ResolveRequestCache += new EventHandler(context_ResolveRequestCache);
context.UpdateRequestCache += new EventHandler(context_UpdateRequestCache);
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
context.PreSendRequestContent += new EventHandler(context_PreSendRequestContent);
context.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders);
context.PostMapRequestHandler += new EventHandler(context_PostMapRequestHandler);
}
void context_Error(object sender, EventArgs e)
{
WriteLog("Error");
//HttpContext.Current.Response.Write("Error
");
}
void context_UpdateRequestCache(object sender, EventArgs e)
{
WriteLog("UpdateRequestCache");
//HttpContext.Current.Response.Write("UpdateRequestCache
");
}
void context_ResolveRequestCache(object sender, EventArgs e)
{
WriteLog("ResolveRequestCache");
// HttpContext.Current.Response.Write("ResolveRequestCache
");
}
void context_RequestCompleted(object sender, EventArgs e)
{
WriteLog("RequestCompleted");
// HttpContext.Current.Response.Write("RequestCompleted
");
}
void context_ReleaseRequestState(object sender, EventArgs e)
{
WriteLog("ReleaseRequestState");
//HttpContext.Current.Response.Write("ReleaseRequestState
");
}
void context_PostUpdateRequestCache(object sender, EventArgs e)
{
WriteLog("PostUpdateRequestCache");
//HttpContext.Current.Response.Write("PostUpdateRequestCache
");
}
void context_PostResolveRequestCache(object sender, EventArgs e)
{
WriteLog("PostResolveRequestCache");
//HttpContext.Current.Response.Write("PostResolveRequestCache
");
}
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
WriteLog("PostRequestHandlerExecute");
//HttpContext.Current.Response.Write("PostRequestHandlerExecute
");
}
void context_PostReleaseRequestState(object sender, EventArgs e)
{
WriteLog("PostReleaseRequestState");
//HttpContext.Current.Response.Write("PostReleaseRequestState
");
}
void context_PostLogRequest(object sender, EventArgs e)
{
WriteLog("PostLogRequest");
//HttpContext.Current.Response.Write("PostLogRequest
");
}
void context_PostAuthorizeRequest(object sender, EventArgs e)
{
WriteLog("PostAuthorizeRequest");
//HttpContext.Current.Response.Write("PostAuthorizeRequest
");
}
void context_PostAuthenticateRequest(object sender, EventArgs e)
{
WriteLog("PostAuthenticateRequest");
//HttpContext.Current.Response.Write("PostAuthenticateRequest
");
}
void context_PostAcquireRequestState(object sender, EventArgs e)
{
WriteLog("PostAcquireRequestState");
//HttpContext.Current.Response.Write("PostAcquireRequestState
");
}
void context_MapRequestHandler(object sender, EventArgs e)
{
WriteLog("MapRequestHandler");
//HttpContext.Current.Response.Write("MapRequestHandler
");
}
void context_Disposed(object sender, EventArgs e)
{
WriteLog("Disposed");
//HttpContext.Current.Response.Write("Disposed
");
}
void context_AuthorizeRequest(object sender, EventArgs e)
{
WriteLog("AuthorizeRequest");
//HttpContext.Current.Response.Write("AuthorizeRequest
");
}
void context_AcquireRequestState(object sender, EventArgs e)
{
WriteLog("AcquireRequestState");
//HttpContext.Current.Response.Write("AcquireRequestState
");
}
void context_PreSendRequestHeaders(object sender, EventArgs e)
{
WriteLog("PreSendRequestHeaders");
//HttpContext.Current.Response.Write("PreSendRequestHeaders
");
}
void context_PreSendRequestContent(object sender, EventArgs e)
{
WriteLog("PreSendRequestContent");
//HttpContext.Current.Response.Write("PreSendRequestContent
");
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
WriteLog("PreRequestHandlerExecute");
//HttpContext.Current.Response.Write("PreRequestHandlerExecute
");
}
void context_EndRequest(object sender, EventArgs e)
{
WriteLog("EndRequest");
//HttpContext.Current.Response.Write("EndRequest
");
}
void context_BeginRequest(object sender, EventArgs e)
{
WriteLog("*******************************************************************************");
HttpApplication app = sender as HttpApplication;
WriteLog(app.Context.Request.Path);
WriteLog("BeginRequest");
//HttpContext.Current.Response.Write("BeginRequest
");
}
void context_AuthenticateRequest(object sender, EventArgs e)
{
WriteLog("AuthenticateRequest");
//HttpContext.Current.Response.Write("AuthenticateRequest
");
}
#endregion
public void OnLogRequest(Object source, EventArgs e)
{
//可以在此处放置自定义日志记录逻辑
WriteLog("OnLogRequest");
//HttpContext.Current.Response.Write("OnLogRequest
");
}
public void context_PostMapRequestHandler(object sender, EventArgs e)
{
WriteLog("PostMapRequestHandler");
//HttpContext.Current.Response.Write("PostMapRequestHandler
");
}
public void WriteLog(string message)
{
string path = @"d:\aspnet\httpmodule.txt";
StreamWriter writer = null;
if (!File.Exists(path))
{
writer = File.CreateText(path);
}
else
{
FileInfo info = new FileInfo(path);
writer = info.AppendText();
}
writer.WriteLine(message);
writer.Flush();
writer.Close();
}
}
BeginRequest #发出信号表示创建任何给定的新请求。 此事件始终被引发,并且始终是请求处理期间发生的第一个事件
AuthenticateRequest #发出信号表示配置的身份验证机制已对当前请求进行了身份验证。 订阅 AuthenticateRequest 事件可确保在处理附加模块或事件处理程序之前对请求进行身份验证
PostAuthenticateRequest #预订 PostAuthenticateRequest 事件的功能可以访问由 PostAuthenticateRequest 处理的任何数据
AuthorizeRequest #发出信号表示 ASP.NET 已对当前请求进行了授权。 订阅 AuthorizeRequest 事件可确保在处理附加的模块或事件处理程序之前对请求进行身份验证和授权
PostAuthorizeRequest #发出信号表示 ASP.NET 已对当前请求进行了授权。 订阅 PostAuthorizeRequest 事件可确保在处理附加的模块或处理程序之前对请求进行身份验证和授权
ResolveRequestCache #引发这个事件来决定是否可以使用从输出缓冲返回的内容来结束请求。这依赖于Web应用程序的输出缓冲时怎样设置的
PostResolveRequestCache #在 ASP.NET 跳过当前事件处理程序的执行并允许缓存模块满足来自缓存的请求时发生
MapRequestHandler #ASP.NET 基础结构使用 MapRequestHandler 事件来确定用于当前请求的请求处理程序
PostMapRequestHandler #在 ASP.NET 已将当前请求映射到相应的事件处理程序时发生
AcquireRequestState #当 ASP.NET 获取与当前请求关联的当前状态(如会话状态)时发生
PostAcquireRequestState #预订 AcquireRequestState 事件的功能可以访问由 PostAcquireRequestState 处理的任何数据
PreRequestHandlerExecute #在ASP.NET开始执行HTTP请求的处理程序之前引发这个事件。在这个事件之后,ASP.NET 把该请求转发给适当的HTTP处理程序
PostRequestHandlerExecute #在 ASP.NET 事件处理程序(例如,某页或某个 XML Web service)执行完毕时发生
ReleaseRequestState #在 ASP.NET 执行完所有请求事件处理程序后发生。 该事件将使状态模块保存当前状态数据
PostReleaseRequestState #在 ASP.NET 已完成所有请求事件处理程序的执行并且请求状态数据已存储时发生
UpdateRequestCache #当 ASP.NET 执行完事件处理程序以使缓存模块存储将用于从缓存为后续请求提供服务的响应时发生
PostUpdateRequestCache #在 ASP.NET 完成缓存模块的更新并存储了用于从缓存中为后续请求提供服务的响应后,发生此事件
OnLogRequest #恰好在 ASP.NET 为当前请求执行任何记录之前发生,即使发生错误,也会引发 LogRequest 事件
PostLogRequest #在 ASP.NET 处理完 LogRequest 事件的所有事件处理程序后发生
EndRequest #在 ASP.NET 响应请求时作为 HTTP 执行管线链中的最后一个事件发生
PreSendRequestContent #恰好在 ASP.NET 向客户端发送内容之前发生,可能发生多次
PreSendRequestHeaders #恰好在 ASP.NET 向客户端发送 HTTP 标头之前发生
RequestCompleted #在任何托管模块和处理程序执行后,它使模块清理资源
HttpHandler与HttpModule不同,一旦定义了自己的HttpHandler类,那么它对系统的HttpHandler的关系将是“覆盖”关系。
public interface IHttpHandler
{
// 摘要:
// 获取一个值,该值指示其他请求是否可以使用 System.Web.IHttpHandler 实例。
//
// 返回结果:
// 如果 System.Web.IHttpHandler 实例可再次使用,则为 true;否则为 false。
bool IsReusable { get; }
// 摘要:
// 通过实现 System.Web.IHttpHandler 接口的自定义 HttpHandler 启用 HTTP Web 请求的处理。
//
// 参数:
// context:
// System.Web.HttpContext 对象,它提供对用于为 HTTP 请求提供服务的内部服务器对象(如 Request、Response、Session
// 和 Server)的引用。
void ProcessRequest(HttpContext context);
}
public class MyIISHandler : IHttpHandler
{
///
文章标题:ASP.NET-自定义HttpModule与HttpHandler
文章链接:http://soscw.com/essay/32237.html