1,当请求到达服务器的时候,asp.net会创建许多对象当作参数,比如HttpRequest表示请求对象参数,HttpResponse表示响应对象参数,还有许多其他的参数,为了方便管理这些参数,asp.net
将他们都封装到了一个参数中:HttpContext(上下文对象),这个对象里包含了所有的这些参数。
2,当HttpContext对象创建完成以后,HttpRuntime将创建一个HttpApplication对象,这个对象
用于处理请求;每一个HttpApplication对象一次仅仅处理一个请求。
在HttpApplication中通过在处理过程中依次发出的多个事件,将这个处理过程分解为多个步骤,这种处理机制叫做处理管道。
为了维护多个事件,在 System.ComponentModel.Component类中的属性Events,这是一个线性字典集合,可以把很多事件保存到这里面。
下面是继承自类Component的一个类,这个类包括4个事件,暴露给程序员注册触发:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleTest { /// <summary> /// 处理管道类,继承自Component /// </summary> class ProcessPipeline:System.ComponentModel.Component { #region 几个对象 private static readonly object startProcess = new object(); private static readonly object preProcess = new object(); private static readonly object postProcess = new object(); private static readonly object endProcess = new object(); #endregion #region 定义事件,public delegate void EventHandler(Object sender, EventArgs e); public event EventHandler StartProcess { add { this.Events.AddHandler(startProcess, value); }//添加时间到集合中 remove { this.Events.RemoveHandler(startProcess, value); }//移除事件 } public event EventHandler PreProcess { add { this.Events.AddHandler(preProcess, value); } remove { this.Events.RemoveHandler(preProcess, value); } } public event EventHandler PostProcess { add { this.Events.AddHandler(postProcess, value); } remove { this.Events.RemoveHandler(postProcess, value); } } public event EventHandler EndProcess { add { this.Events.AddHandler(endProcess, value); } remove { this.Events.RemoveHandler(endProcess, value); } } #endregion #region 触发事件 protected void OnStartProcess(EventArgs e) { if (this.Events[startProcess] != null) { (this.Events[startProcess] as EventHandler)(this, e); } } protected void OnPreProcess(EventArgs e) { if (this.Events[preProcess] != null) { (this.Events[preProcess] as EventHandler)(this, e); } } protected void OnPostProcess(EventArgs e) { if (this.Events[postProcess] != null) { (this.Events[preProcess] as EventHandler)(this, e); } } protected void OnEndProcess(EventArgs e) { if (this.Events[endProcess] != null) { (this.Events[endProcess] as EventHandler)(this, e); } } #endregion #region 通过一个方法触发所有的事件 public void Process() { Console.WriteLine("开始处理"); this.OnStartProcess(EventArgs.Empty); //触发事件之后就会调用事件对应的具体方法pipe_StartProcess(object sender, EventArgs e) Console.WriteLine("处理之前"); this.OnPreProcess(EventArgs.Empty); Console.WriteLine("正在处理"); this.OnPostProcess(EventArgs.Empty); Console.WriteLine("处理完成"); this.OnEndProcess(EventArgs.Empty); } #endregion } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Noesis.Javascript; using System.Net; using System.Net.Sockets; using System.Collections; using System.Windows.Forms; using System.Runtime.Remoting; using System.Runtime; using System.Web; namespace ConsoleTest { class Program { static void Main(string[] args) { ProcessPipeline pipe = new ProcessPipeline(); #region 注册事件 pipe.StartProcess += new EventHandler(pipe_StartProcess); pipe.PreProcess += new EventHandler(pipe_PreProcess); pipe.PostProcess += new EventHandler(pipe_PostProcess); pipe.EndProcess += new EventHandler(pipe_EndProcess); #endregion pipe.Process();//触发所有的事件 } static void pipe_EndProcess(object sender, EventArgs e) { Console.WriteLine("处理结束的处理过程"); //throw new NotImplementedException(); } static void pipe_PostProcess(object sender, EventArgs e) { Console.WriteLine("处理过程的事件处理"); //throw new NotImplementedException(); } static void pipe_PreProcess(object sender, EventArgs e) { Console.WriteLine("处理之前的事件处理"); //throw new NotImplementedException(); } static void pipe_StartProcess(object sender, EventArgs e) { Console.WriteLine("开始处理的事件处理"); //throw new NotImplementedException(); } } }
3,asp.net创建了HttpApplication对象,然后使用处理管道的方式为程序员暴露许多事件,
这些事件按照固定的顺序触发,我们只需要注册相关的事件,并且在事件对应的方法中处理。
在asp.net中,用于处理请求以得到结果的对象叫做处理程序Handler,HttpContext的
Handler属性就表示这个处理程序对象。
AcquireRequestState事件让程序员可以得到用户以前保存的专有数据(比如session).
如果在HttpApplication的各个事件之间传递参数,可以使用HttpContext的Items属性。
4,获取HttpApplication对象的引用的方式有两种:IHttpModule方式和global.asax方式。
5,下面是一个IHttpModule的具体例子:
先定义个实现了IHttpModule接口的类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WebApplication2 { /// <summary> /// 自定义HttpModule,继承自IHttpModule /// </summary> public class HelloWorldModule:IHttpModule { /// <summary> /// 释放资源 /// </summary> public void Dispose() { } /// <summary> /// 初始化事件 /// </summary> /// <param name="context"></param> public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); context.EndRequest += new EventHandler(context_EndRequest); } void context_EndRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context;//得到httpContext string filePath = context.Request.Path;//得到请求路径 string fileExtension = VirtualPathUtility.GetExtension(filePath);//得到文件的扩展名 if (fileExtension == ".aspx") { context.Response.Write("<h1 style=\"color:red\">Hello World,Module,Ending of request.</h1><br />"); } } /// <summary> /// 开始请求事件BeginRequest对应的方法 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void context_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context;//得到httpContext string filePath = context.Request.Path;//得到请求路径 string fileExtension = VirtualPathUtility.GetExtension(filePath);//得到文件的扩展名 if (fileExtension == ".aspx") { context.Response.Write("<h1 style=\"color:red\">Hello World,Module,Beginning of request.</h1><br />"); } } } }
然后在配置文件web.config中注册,在<System.Web><HttpModules>添加自己的HttpModule。
<httpModules> <add name="MyModule1" type="WebApplication2.HelloWorldModule,WebApplication2"/> </httpModules>
添加HttpModule配置有两个必须的属性,那就是name和type,name属性可以随意,但是不能跟其他HttpModule有重名;type 属性有两部分组成,他们以英文逗号隔开,第一部分是自定义HttpModule(HelloWorldModule)类的完整路径,第二不部分是自定义 HttpModule类所在的命名空间的完整路径。
这个例子来自:http://www.cnblogs.com/jiangzhichao/archive/2011/07/03/2096674.html