最近学习WCF知识时看到有关IIS版本的知识,发现对HttpContext,HttpModule,HttpHandler的内容都不是很了解,这三个也是ASP.NET相对基础的内容,晚上特地花点时间针对HttpModule的内容进行补充,文中的理论知识都是从网上多方面整理,最后的实例是本人所写的两个小实例,主要是针对HttpModule的运用;
一:关于HttpModule理论知识
1:HttpModule概述
HttpModule是实现了IHttpModule接口的程序集。一般来说,我们可以将Asp.Net中的事件分成三个级别,最顶层是 应用程序级事件、其次是页面级事件、最下面是控件级事件,事件的触发分别与 应用程序周期、页面周期、控件周期紧密相关。而 Http Module 的作用是与应用程序事件密切相关的。
注意:在http请求的处理过程中,只能调用一个HttpHandler,但可以调用多个HttpModule。
2:HttpModules作用:
ASP.NET请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,当请求到达HttpModule的时候,系统还没有对这个请求真正处理,但是我们可以在这个请求传递到处理中心(HttpHandler)之前附加一些其它信息,或者截获的这个请求并做一些额外的工作,也或者终止请求等。HttpHandler处理完请求之后,我们可以再在相应的HttpModule中把请求处理的结果进行再次加工返回客户端。
3:Http模块可以向System.Web.HttpApplication对象注册下面一系列事件:
AcquireRequestState 当ASP.NET运行时准备好接收当前HTTP请求的对话状态的时候引发这个事件。
AuthenticateRequest 当ASP.NET 运行时准备验证用户身份的时候引发这个事件。
AuthorizeRequest 当ASP.NET运行时准备授权用户访问资源的时候引发这个事件。
BeginRequest 当ASP.NET运行时接收到新的HTTP请求的时候引发这个事件。
Disposed 当ASP.NET完成HTTP请求的处理过程时引发这个事件。
EndRequest 把响应内容发送到客户端之前引发这个事件。
Error 在处理HTTP请求的过程中出现未处理异常的时候引发这个事件。
PostRequestHandlerExecute 在HTTP处理程序结束执行的时候引发这个事件。
PreRequestHandlerExecute 在ASP.NET开始执行HTTP请求的处理程序之前引发这个事件。在这个事件之后,ASP.NET 把该请求转发给适当的HTTP处理程序。
PreSendRequestContent 在ASP.NET把响应内容发送到客户端之前引发这个事件。这个事件允许我们在内容到达客户端之前改变响应内容。我们可以使用这个 事件给页面输出添加用于所有页面的内容。例如通用菜单、头信息或脚信息。
PreSendRequestHeaders 在ASP.NET把HTTP响应头信息发送给客户端之前引发这个事件。在头信息到达客户端之前,这个事件允许我们改变它的内容。我们可以使用这个事件在头信息中添加cookie和自定义数据。
ReleaseRequestState 当ASP.NET结束所搜有的请求处理程序执行的时候引发这个事件。
ResolveRequestCache 我们引发这个事件来决定是否可以使用从输出缓冲返回的内容来结束请求。这依赖于Web应用程序的输出缓冲时怎样设置的。
UpdateRequestCache 当ASP.NET完成了当前的HTTP请求的处理,并且输出内容已经准备好添加给输出缓冲的时候,引发这个事件。这依赖于Web应用程序的输出缓冲是如何设置的。
注意: BeginRequest和PreRequestHandlerExecute之间的事件是在服务器执行HttpHandler处理之前触发。
PostRequestHandlerExecute和PreSendRequestContent之间的事件是在服务器执行Handler处理之后触发。
4:HttpModule生命周期示意图
5:HttpModule实现:
HTTP模块是实现了System.Web.IhttpModule接口的类。IHttpModule接口的声明:
public interface IHttpModule
{
void Init (HttpApplication context);
void Dispose ();
}
Init 方法:系统初始化的时候自动调用,这个方法允许HTTP模块向HttpApplication 对象中的事件注册自己的事件处理程序。
Dispose方法: 这个方法给予HTTP模块在对象被垃圾收集之前执行清理的机会。此方法一般无需编写代码。
二:HttpModule实例(分别用两个HttpModule来演示):
(1)第一个实例是演示实现站点所有页面的头部跟尾部都同时输出相同的内容:
步骤一:我们新建一个类让它继承接口IHttpModule;并让它实现两个事件,用于分别输出
using System.Web; /// <summary> ///TestModule 的摘要说明 /// </summary> public class TestModule:IHttpModule { public TestModule() { } public void Dispose() { throw new NotImplementedException(); } public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_StartRequest); context.EndRequest += new EventHandler(context_EndRequest); } /// <summary> /// 所有页面头部显示 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void context_StartRequest(object sender, EventArgs e) { HttpApplication ha = (HttpApplication)sender; ha.Response.Write("页面加载前的内容"); } /// <summary> /// 所有页面尾部显示 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void context_EndRequest(object sender, EventArgs e) { HttpApplication ha = (HttpApplication)sender; ha.Response.Write("内容加载后的内容"); } }
步骤二:修改web.config 增加配置信息
<httpModules> <add name="TestModule" type="TestModule,App_Code"/> </httpModules>
name:模块名称,一般是类名
type:有两部分组成,前半部分是命名空间和类名组成的全名,后半部分是程序集名称,如果类是直接放在App_Code文件夹中,那程序名称是App_Code。
步骤三:查看运行效果(其中中间是我们当前页的内容):
(2)第二个实例是我们平时系统登录功能,实例把用户信息保存到Cookies中;在HttpModule进行统一判断,解决以前每个页面或者写个父类来进行判断的麻烦;
步骤一:首先我们同样新建一个类LoginModule继承自IHttpModule
using System.Web; public class LoginModule:IHttpModule { public LoginModule() { } public void Dispose() { throw new NotImplementedException(); } public void Init(HttpApplication context) { context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute); } void context_PreRequestHandlerExecute(object sender, EventArgs e) { HttpApplication ha = (HttpApplication)sender; string path = ha.Context.Request.Url.Segments[2].ToString(); //获得访问的页面 bool IsLogingPage = path.ToLower().Equals("login.aspx"); //比较是否是Login.aspx 是就不进入 if (!IsLogingPage) { var CookiesDemo = ha.Context.Request.Cookies["HttpDemo"]; if ( CookiesDemo== null) { ha.Context.Response.Redirect("Login.aspx"); } } } }
步骤二:修改web.config
<httpModules> <add name="LoginModule" type="LoginModule,App_Code"/> </httpModules>
步骤三:在登录页Login.aspx 实现一个针对Cookie的写入功能;
protected void Button1_Click(object sender, EventArgs e) { HttpCookie ck = new HttpCookie("HttpDemo"); ck.Values.Add("UserID", "踏浪帅"); Response.SetCookie(ck); Response.Redirect("Default.aspx"); }
步骤四:在首页Default.aspx 实现一个清除Cookie的功能,达到一个退出的功能
protected void Button1_Click(object sender, EventArgs e) { ClearCookie("HttpDemo"); Server.Transfer("Login.aspx"); } public static void ClearCookie(string cookiename) { HttpCookie cookie = HttpContext.Current.Request.Cookies[cookiename]; if (cookie != null) { cookie.Expires = DateTime.Now.AddYears(-3); HttpContext.Current.Response.Cookies.Add(cookie); } }
效果:当没有在Login.aspx实现登录(写入Cookie)而直接访问首页Default.aspx时系统会自动跳转到Login.aspx;