稍作停留的思绪(ASP.NET 处理管道)

阅读了《ASP.NET 本质论》,稍微按自己的思路总结一下ASP.NET的处理管道,首先是一个HttpApplication的处理管道的工作流程图:

 

HttpApplication 对象是ASP.NET中处理请求的重要对象,它是由ASP.NET自己创建,并且暴露了很多事件供程序员调用。

如果在HttpApplication的事件处理过程中希望传递一些有用的数据,那么可以使用HttpContext,它有一个Item属性,该属性是一个字典对象,那么就可以将自定义的数据往里面装其他事件中再取出数据使用即可。

既然已经知道能够在整个Http的请求应答过程的流程能够使用HttpApplication对象来进行注入式的处理,那么如何得到HttpApplication对象的实例呢?毕竟这个喽罗是由ASP.NET来创建的,而不是由程序员自己创建的。ASP.NET当然也就提供了解决方案,主要有两种。

两种方式。IHttpModule接口专门用来定义HttpApplication对象的事件处理。IHttpModule接口的声明如下:

public interface IHttpModule
{
    void Dispose();
    void Init(HttpApplication context);
}

比如,希望编写一个处理HttpApplication对象PostAuthenticateRequest事件的HttpModule,那么可以如下完成事件的注册:

public void Init(HttpApplication context)
{
    context.PostAuthenticateRequest += new EventHandler(
      Application_PostAuthenticateRequest);
}

注册IHttpModule,在ASP.NET的网站配置文件web.config中,system.web配置元素的子元素httpModules用来配置网站所使用的HttpModule

httpModules的子元素add用来增加一个新的HttpModule;clear将清除前面注册的所有HttpModule

add元素有两个必选属性name和type。

  • name表示这个HttpModule在程序中的名字,通过该名字可以在Web Application找到HttpModule对象的引用。HttpApplication的Modules属性表示这个对象所关联的所有HttpModules对象,通过这个name索引器可以找到对应的HttpModule对象。

  • type表示HttpModule对象的类型名,ASP.NET通过该类型名进行反射来动态创建HttpModule对象。如果这个类定义在网站中,那么,就是一个包含命名空间的类的全名,否则,在全名的后面,使用逗号分隔,还需要跟上类型所在的程序集名称,程序集名称不需要包含扩展名。

比如,自定义的HttpModule类位于程序集OnlineUserModule中,类的全名为com.aspnet.OnlineUserModule,将这个自定义的HttpModule注册到网站中,那么配置文件中定义如下所示:


  

对于 IIS7.0来说,还需要在配置文件的system.webServer配置节中注册HttpModule。此时的配置元素名称变为了modules。在 IIS7.0中,可以为MapRequestHandler,LogRequest和PostLogRequest事件添加处理程序。只有在 IIS 7.0 集成模式下运行并且与.NET Framework 3.0或更高版本一起运行的应用程序,才可以支持这些事件。


  
    
  

而通过global.asax创建HttpApplication事件处理程序则相对更加容易一些。

由Visual Studio创建的每个普通网站项目中都存在一个叫做global.asax的文件,在调试模式下运行网站,如果是在Windows 7操作系统,则会在C:\Users\用户名\AppData\Local\Temp\Temporary ASP.NET Files\项目名称\可以看到一个类似App_global.asax.vhopxkyt.0.cs的代码文件。就可以看到

public class global_asax : global::System.Web.HttpApplication
{
   ......
}

那么,想要给HttpApplication挂接事件怎么办?直接在global.asax中定义一个符合事件签名的public 方法即可。而这些方法都是有特殊的命名规范的:

  1. 这些方法必须符合System.EventHandler签名,因为所有的HttpApplication的管道事件都是该委托类型;
  2. 方法的作用域必须是public;
  3. 方法的命名格式必须如下:Application_注册的事件名称。

其实,使用global.asax最常用的场景是编写一些特殊的事件处理代码。

  1. Start 事件
  2. End 事件
  3. Error 事件
  4. Session 的 Start 事件
  5. Session 的 End 事件

两个特殊的事件

  1. PreSendRequestHeaders

    当准备从HttpResponse回应发送HTTP的Header之前,HttpApplication将会触发PreSendRequestHeaders事件。在这个事件中,可以根据发送的Header来动态设置一些参数,比如,如果通过Content-Type参数获知发送的内容是text/html网页,那么,可以通过启用输出的压缩来提高网络的传输速度。这个操作可以通过设置一个特殊的Header来通知浏览器。

  2. PreSendRequestContent

    当准备通过 HttpResponse 回应发送 HTTP 的 Body 内容之前,HttpApplication 将会触发 PreSendRequestContext事件。如果配置了输出到客户端的压缩,那么,可以在这个事件中包装输出到浏览器的流以实现输出的压缩

Pop Jungle是我的新作,希望大家喜欢
原文地址:https://www.cnblogs.com/CoolJie/p/2079766.html