Asp.Net高级知识回顾_HttpModule及应用程序生命周期_1
为什么asp.net落后了,还讲这些?因为mvc 还是沿用老框架的,加了一个请求模块,在第七个事件中触发;
一、概念
HTTP模块(HttpModule)是通过实现IHttpModule接口和处理事件,在每次针对应用程序发出请求时调用的程序集。HTTP模块作为ASP.NET请求管线的一部分调用,能够在整个请求过程中访问生命周期事件。因此,HTTP模块使我们有机会检查传入和传出的请求,并根据该请求采取操作,甚至我们可以通过实现HTTP模块来参与ASP.NET的运行管理。
二、托管管道模式(IIS应用程序池)
1. 经典模式
在IIS7之前,ASP.NET是以IIS ISAPI Extension的方式外加到IIS。然后IIS根据要求的内容类型做判断,如果是HTML静态网页就由IIS自行处理,如果不是,就根据要求的内容类型,分派给各自的IIS ISAPI Extension,如果要求的内容类型是ASP.NET,就分派给负责处理ASP.NET的IIS ISAPI Extension,也就是aspnet_isapi.dll。IIS7应用程序池托管管道模式中的“经典模式”也是这样的工作原理,这种模式是兼容IIS 6的方式,以减少升级成本。下图是这个架构的示意图:
2. 集成模式
IIS7完全整合 .NET 之后,架构的处理顺序有了很大不同,最大变化是ASP.NET从IIS插件(ISAPI Extension)的角色进入了 IIS 核心,并且能以ASP.NET模块处理IIS7的诸多类型要求。这些ASP.NET模块不只能处理ASP.NET网页程序,也能处理其他程序;看图吧:
3. IIS5、IIS6中的生命周期,处理顺序
a. 用户从Web服务器请求应用程序资源。
ASP.NET应用程序的生命周期以浏览器向Web服务器(对于ASP.NET应用程序,通常为IIS)发送请求为起点。ASP.NET是Web服务器下的ISAPI扩展。Web服务器接收到请求时,会对所请求文件的文件扩展名进行检查,确定应由哪个ISAPI扩展处理该请求,然后将该请求传递给合适的ISAPI扩展。ASP.NET处理已映射到其上的文件扩展名,如.aspx、.ascx、.ashx 和 .asmx。
如果文件扩展名尚未映射到ASP.NET,则ASP.NET将不会接收该请求。对于使用ASP.NET身份验证的应用程序,理解这一点非常重要。 例如.htm 文件,通常没有映射到ASP.NET,因此ASP.NET将不会对.htm 文件请求执行身份验证或授权检查,因此,即使文件仅包含静态内容,想要 ASP.NET 检查身份验证,应使用映射到ASP.NET的文件扩展名创建该文件,如采用.aspx文件扩展名。
如果要创建服务于特定文件扩展名的自定义处理程序(httphandler),必须在IIS中将该扩展名映射到ASP.NET,还必须在应用程序的Web.config文件中注册该处理程序。
b.ASP.NET接收对应用程序的第一个请求。
当ASP.NET接收到对应用程序中任何资源的一个请求时,名为ApplicationManager的类会创建一个应用程序域。www站点运行于其中。我们都知道,在同一个IIS上,两个web应用程序的应用程序域都是独立的(隔离的)。因此一个应用程序域中问题不会影响到其它应用程序域。在应用程序域中,将为名为 HostingEnvironment的类创建一个实例,该实例提供有关应用程序的信息(如存储该应用程序的文件夹名称)访问。
下面的关系图说明了这种关系:
c. 为每个请求创建ASP.NET核心对象。
创建应用程序域并对HostingEnvironment对象进行了实例化之后,ASP.NET将创建并初始化核心对象,如HttpContext、HttpRequest和HttpResponse。HttpContext类包含特定于当前应用程序请求的对象,如 HttpRequest和HttpResponse对象。HttpRequest对象包含有关当前请求的信息,包括Cookie和浏览器信息。HttpResponse对象包含发送到客户端的响应,包括所有呈现的输出和Cookie。
d.将HttpApplication对象分配给请求。
初始化所有核心应用程序对象之后,将通过创建HttpApplication类的实例启动应用程序。如果应用程序具有Global.asax文件,则ASP.NET将创建Global.asax类(从 HttpApplication 类派生)的一个实例,并使用该派生类表示应用程序。
第一次在应用程序中请求ASP.NET页或进程时,将创建HttpApplication的一个新实例。为了尽可能提高性能,可对多个请求重复使用HttpApplication实例。
创建HttpApplication的实例时,将同时创建所有已配置的模块。创建了所有已配置的模块之后,将调用HttpApplication类的Init 方法。
下面的关系图说明了这种关系:
e: 由HttpApplication管线处理请求。
在处理该请求时将由HttpApplication 类执行HttpModule事件。
4. IIS7中的生命周期
a.发出一个对应用程序资源的请求。
ASP.NET应用程序的生命周期以浏览器向Web服务器发送请求为起点。
在IIS7.0经典模式下,以及IIS6.0中,ASP.NET请求管道与Web服务器管道分离,模块仅应用于路由到ASP.NET ISAPI扩展的请求,如果请求资源类型的文件扩展名未显式映射到 ASP.NET,则不会为该请求调用ASP.NET功能,如静态文件,原因是ASP.NET运行时没有处理该请求。
而在IIS7.0集成模式下,由一个统一的管道处理所有请求,当集成管道收到请求时,该请求将经历所有请求共有的一些阶段,这些阶段由RequestNotification枚举表示,所有请求都可以配置为使用ASP.NET功能,该功能封装在可以访问请求管道的托管代码模块中。例如,即使 .htm文件扩展名未显式映射到ASP.NET,对HTML页的请求仍会调用ASP.NET模块。这使得我们可以对所有资源使用ASP.NET身份验证和授权。
b. 统一管道接收对应用程序的第一个请求。
当统一管道接收对应用程序中的任何资源的第一个请求时,将为ApplicationManager类创建一个实例,该实例就是处理请求的应用程序域,应用程序域提供了应用程序之间全局变量的分离,并且使每个应用程序能够单独卸载。在应用程序域中,将为HostingEnvironment类创建一个实例,该实例提供对有关应用程序的信息(如存储该应用程序的文件夹的名称)的访问。
c. 将为每个请求创建响应对象。
在创建应用程序域并对HostingEnvironment对象进行实例化之后,将创建并初始化应用程序对象,如 HttpContext、HttpRequest和HttpResponse。HttpContext类包含特定于当前应用程序请求的对象,如 HttpRequest和HttpResponse对象。HttpRequest对象包含有关当前请求的信息,包括 Cookie 和浏览器信息。HttpResponse对象包含发送到客户端的响应,其中包括所有呈现的输出和Cookie。
d.将HttpApplication对象分配给请求。
初始化所有应用程序对象之后,将通过创建HttpApplication类的实例来启动应用程序。如果应用程序有 Global.asax文件,则ASP.NET将创建从HttpApplication类派生的Global.aspx类的实例。然后使用该派生类来表示应用程序。
第一次在应用程序中请求ASP.NET页或进程时,将创建HttpApplication类的一个新实例。为了尽可能提高性能,可对多个请求重复使用HttpApplication 实例。
加载哪些ASP.NET模块取决于应用程序从父应用程序继承的托管代码模块,还取决于在应用程序的Web.config文件的配置节中配置了哪些模块。在应用程序的Web.config的 system.webServer节中的modules元素中添加或移除模块。我会专门写一张文章记录常用的webconfig
f.由HttpApplication 管线处理请求。
在处理请求时,HttpApplication类会执行一些系列的事件,如果是开发自定义模块,并且希望对发往管道的所有请求都调用该模块,则这些事件也很有用。自定义模块实现IHttpModule接口,在IIS7.0集成模式下,必须在模块的Init方法中注册事件处理程序。