• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Asp.net的生命周期之应用程序生命周期

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

参考:http://msdn.microsoft.com/zh-cn/library/ms178473(v=vs.100).aspx

参考:http://www.cnblogs.com/JimmyZhang/archive/2007/09/04/880967.html

Http请求刚刚到达服务器的时候

当服务器接收到一个 Http请求的时候,IIS (Internet Information Services,互联网信息服务)首先需要决定如何去处理这个请求

什么是IIS?

IIS是一种Web(网页)服务组件,(其中包括Web服务器、FTP服务器、NNTP服务器和SMTP服务器,分别用于网页浏览、文件传输、新闻服务和邮件发送等方面,它使得在网络(包括互联网和局域网)上发布信息成了一件很容易的事。对于IIS来说,它依赖一个叫做 HTTP.SYS 的内置驱动程序来监听来自外部的 HTTP请求IIS支持的东西也比较多,最常见的就是处理多媒体的功能(例如:为什么请求的图片会被显示在客户端?就是IIS进行处理的。这也是为什么要防图片盗链:若图片被盗链,在其它网站打开本站图片同样占一个iis,而你的IIS资源是有限的),当然如果你进行了设置,图片的处理也能交由应用程序进行处理。 

在操作系统启动的时候,IIS首先在HTTP.SYS中注册自己的虚拟路径(实际上相当于告诉HTTP.SYS哪些URL是可以访问的,这也是为什么你访问不存在的文件会出现 404 错误),如果请求的是一个可访问的URL,HTTP.SYS会将这个请求交给 IIS 工作者进程。

 

注:一会要说的aspnet_isapi.exe,在IIS6.0中叫做 w3wp.exe,IIS5.0中叫做 aspnet_wp.exe。

IIS是怎么识别这些Asp、Java、VBscript、Asp.Net等程序发布的页面,依据的是什么呢?

答:根据文件的后缀名。

服务器获取所请求的页面(也可以是多媒体、文件(也有后缀名)等)的后缀名以后,接下来会在服务器端寻找可以处理这类后缀名的应用程序。IIS不可能处理各种后缀名的应用程序,要处理这些,就要借助 ISAPI 应用程序(NOTE:Internet Server Application Programe Interface,互联网服务器应用程序接口)。ISAPI实际上只是一个接口,起到一个代理的作用,它的主要工作是映射所请求的页面(文件)  和与此后缀名相对应的实际的处理程序。

除了映射文件与其对应的处理程序以外,ISAPI 还需要做一些其他的工作:

  1. 从HTTP.SYS中获取当前的Httq请求信息,并且将这些信息保存到 HttpWorkerRequest 类中。
  2. 在相互隔离的应用程序域AppDomain中加载HttpRuntime。
  3. 调用 HttpRuntime的ProcessRequest方法。

让我们更进一步地看一下 ISAPI ,看看它到底是什么样子,请按下面的步骤进行:

  1. 打开IIS。
  2. 选择随意一个站点,鼠标右键,“属性”。
  3. 选择“主目录”选项卡。
  4. 选择“配置”。

你应该会看到如下的画面:

图1. 应用程序配置

很清楚地就可以看到,所有IIS所能处理,或者叫 ISAPI 所提供代理服务的 文件类型 及其相对应的实际的后台处理程序都在这里清楚地列出来了。

我们找到 .aspx 的应用处理程序,然后点“编辑”,会出现下面的画面:

图2. 编辑.aspx文件的处理程序

可以看出,所有的.aspx文件实际上都是由 aspnet_isapi.dll 。这个程序来处理的,当IIS把对于.aspx页面的请求提通过ISAPI交给了aspnet_isapi.dll以后,接着就是只是等待结果,返回给用户(实际是IIS 接收返回的数据流,并重新返还给 HTTP.SYS,最后,HTTP.SYS 再将这些数据返回给客户端浏览器。)。现在我们应该知道:Asp.Net 只是服务器(IIS)的一个组成部分而已,它是一个 ISAPI扩展。

Ps:到这里我们就应该大致知道,一个请求到服务器后,这个请求是怎么样被处理的(至于怎么到的,那是网络传输中的事)。我们还要知道一个内容(可能有点多余),我们开发的网站是部署在服务端的,这个网页是输入网址就能直接看的,这些程序是经过发布的。这多少和你本地运行程序有点类似)。

应用程序生命周期前:编译

 

下表描述编译 ASP.NET 顶级项的顺序。

 

说明
App_GlobalResources 应用程序的 Bin 文件夹中的任何程序集都链接到资源程序集。
App_WebResources 所生成的 Web 引用程序集将链接到资源程序集(如存在)。
Web.config 文件中定义的配置文件属性 如果应用程序的 Web.config 文件中定义了配置文件属性,则生成一个包含配置文件对象的程序集。
App_Code 所有代码程序集和配置文件程序集都链接到资源和 Web 引用程序集(如果有)。
Global.asax 编译应用程序对象并将其链接到所有先前产生的程序集。

 

下表描述编译 ASP.NET 文件夹和项的顺序。 

 

说明
App_LocalResources 如果包含被请求项的文件夹包含 App_LocalResources 文件夹,则编译本地资源文件夹的内容并将其链接到全局资源程序集。
各个网页(.aspx 文件)、用户控件(.ascx 文件)、HTTP 处理程序(.ashx 文件)和 HTTP 模块(.asmx 文件) 根据需要编译并链接到本地资源程序集和顶级程序集。
主题、主控页、其他源文件 在编译引用页时编译那些页所引用的各个主题、主控页和其他源代码文件的外观文件。

 

编译后的程序集缓存在服务器上并在后续请求时被重用,并且只要源代码未更改,就会在应用程序重新启动之间得到保留。 

上面的是MSDN中的,咱说点别的:在编译时,.aspx其实是属于前台页面,当然也可以在前台写C#代码,这只和选的编程模式有关。执行的程序都是被编译了的,简单的说,就是页面是没法子运行的,只有编译后才能执行。.aspx编译后是前台继承与后台。后台的页码编译成程序集,而前台代码是根据的选择模式有关。网站将前台页面 直接以前台页面类的方式 编译到程序集里;网站应用程序,只能编译 后台页面类到程序集,前台页面必须在被访问的时候 才编译到程序集中。当然.aspx页面有三种控件,分别是Html标签、Html服务器控件、服务器控件三种,这些控件会被编译成不同的类,他们的简洁性是由低到复杂的(此处有空再整下三种控件的区别)。

 

应用程序生命周期概述

说这么多也没说到应用程序的生命生命周期。程序的生命周期也是有几种的,有应用程序生命周期、Asp.Net页生命周期、控件生命周期等。

参考MSDN地址:

http://msdn.microsoft.com/zh-cn/library/ms178473(v=vs.100).aspx   这是IIS5和IIS6的

http://msdn.microsoft.com/zh-cn/library/bb470252(v=vs.100).aspx    这是IIS7的

我们注意:

在 IIS 6.0 中,有两个请求处理管道。 一个管道用于本机代码 ISAPI 筛选器和扩展组件。 另一个管道用于托管代码应用程序组件,如 ASP.NET。

在 IIS 7.0 中,ASP.NET 运行时与 Web 服务器集成,这样就有了一个针对所有请求的统一的请求处理管道。

我的梳理是以IIS5和IIS6为基本,毕竟程序是向下兼容的。以下文字大部分是MSDN的东西,有些图是自己找的。

1.用户从Web服务器请求应用程序

ASP.NET 处理已映射到其上的文件扩展名,如 .aspx、.ascx、.ashx 和 .asmx。

http://msdn.microsoft.com/zh-cn/library/bb398986%28v=vs.100%29.aspx)。不建议这些交由Asp.Net处理,毕竟资源有限。

.aspx、.ascx、.ashx 和 .asmx等文件的处理过程吧。

 

2.ASP.NET 接收对应用程序的第一个请求

当用户请求的文件的后缀名为: .aspx、.ascx、.ashx 和 .asmx时,IIS会把这个请求交由ISAPI ,ISAP找到aspnet_ISAPI,然后让aspnet_ISAPI进行处理。

在应用程序域中,将为名为 HostingEnvironment 的类创建一个实例,该实例提供对有关应用程序的信息(如存储该应用程序的文件夹的名称)的访问。

看不懂没关系想来看下他们分别是干什么的:

该对象负责:

  • 激活和初始化 ASP.NET 应用程序;
  • 管理应用程序生存期和在应用程序中注册的对象的生存期;
  • 公开宿主环境使用的对象以处理 ASP.NET 应用程序请求;
  • 提供任意给定时刻运行于宿主进程中的应用程序的列表;

再看下应用程序域是干啥的:为全局变量提供应用程序隔离,并允许单独卸载每个应用程序。这时再看看上面的那张图(PS:想成此时只有一次请求),不难理解:要进行管理还得需要一个第三方来对宿主对象和ApplicationManager之间进行信息交流,且这个第三方还得在在应用程序域中,而这第三方就是HostingEnvironment。

HostingEnvironment的作用是什么呢?HostingEnvironment 类的一个静态实例,该实例提供对应用程序管理功能和应用程序服务的访问。

为了尽可能提高性能,进程就要对多个请求进行重复使用这个HttpApplication 实例。 

, 在CLR初始化的使用会加载两个重要的dll:AppManagerAppDomainFactory和ISAPIRuntime。通过 AppManagerAppDomainFactory的Create方法为Application创建一个Application Domain;通过ISAPIRuntime的ProcessRequest处理Request,进而将流程拖入到ASP.NET Http Runtime Pipeline。   

 

如下图:

 

图注:为了避免用户应用程序访问或者修改关键的操作系统数据,windows提供了两种处理器访问模式:用户模式(User Mode)和内核模式(Kernel Mode)。一般地,用户程序运行在User mode下,而操作系统代码运行在Kernel Mode下。Kernel Mode的代码允许访问所有系统内存和所有CPU指令。 在User Mode下,http.sys接收到一个基于aspx的http request,然后它会根据IIS中的Metabase查看该基于该Request的Application属于哪个Application Pool,如果该Application Pool不存在,则创建之。否则直接将request发到对应Application Pool的Queue中。摘自:http://www.cnblogs.com/artech/archive/2007/09/09/887528.html

允许单独卸载每个应用程序是怎么回事呢?

原因就是因为有隔离。Http请求被分放在相互隔离的应用程序域中,当 Web.config文件的内容发生改变 或者 .aspx文件发生变动的时候,能够卸载运行在同一个进程中的应用程序(卸载也是为了重新加载)。注:这也是为什么配置文件发生改变时,程序能立即更改,当然这个还和接口有关系

3.为每个请求创建 ASP.NET 核心对象

HttpResponse

HostingEnvironment 构造函数仅由应用程序的 ApplicationManager 对象调用一次

  • HttpContext 类包含特定于当前应用程序请求的对象,如 HttpRequest 和 HttpResponse 对象。
  •  对象包含有关当前请求的信息,包括 Cookie 和浏览器信息。
  • 呈现的输出和 Cookie。

上面是MSDN的描述。下面是了解到初始化Asp.Net核心对象的过程,主要是通过反编译,我觉得合理。

public sealed class ISAPIRuntime : MarshalByRefObject, IISAPIRuntime, IRegisteredObject
分析:

a.继承MarshalByRefObject:从而以此获得跨应用程序访问对象的能力。

b.实现 IISAPIRuntime接口,来看下这个接口里一个最重要的方法:

[return: MarshalAs(UnmanagedType.I4)]
int ProcessRequest([In] IntPtr ecb, [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);

  注意看第一个参数:IntPtr ecb,是一个指针对象,其实就是保存的aspnet_isapi.dll的引用,为什么要位ProcessRequest方法传入这个指针?因为ASP.NET需要通过这个指针对应的aspnet_isapi.dll对象 从IIS处获得浏览器发来的请求报文,并且当ASP.NET最后处理完页面生成响应报文后,也要通过它将响应报文发回给IIS再有IIS发回到浏览器。

 c.继承MarshalByRefObject的原因也就是为了能访问到托管代码外的这个aspnet_isapi.dll。

HttpWorkerRequest wr),开始处理请求。

HttpRuntime中调用的ProcessRequestInternal(HttpWorkerRequest wr)做了3个重要的事情:
 a.生成上下文对象(HttpContext),为上下文对象context内部的两个重要的成员赋值:Reqeust和Response,前者负责向ASP.NET和程序员提供请求报文的数据,后者向ASP.NET和程序员提供储存要输出到浏览器的数据的地方。
          (I).内部的HttpRequest对象:根据wr里封装的报文数据进一步封装出了HttpRequest对象。
          (II).内部的HttpResponse对象:在内部初始化了一个HtmlWriter对象,用来保存服务端要输出给浏览器的页面代码。
          (III).注意,如果在创建context时出现错误,比如浏览器发来的请求报文格式错误,那么就会直接在此时向浏览器输出400响应报文。
 b.创建HttpApplication handler,此对象中执行请求的动态页面对象创建和执行的整个过程。
  (I).通过HttpApplicationFactory创建——HttpApplicationFactory.GetApplicationInstance(context) ;(具体方法)。注意:此方法中为创建的HttpApplication对象传入了上下文对象context。
  (II).HttpApplication具体执行过程。
 c.当HttpApplication执行完后,调用FinishRequest方法,生成并输出响应报文到浏览器。

HttpRuntime中调用的ProcessRequestInternal(HttpWorkerRequest wr)之后的大致流程

 

MSDN对创建自定义进程管线或自定义宿主环境的开发人员应该在从 HttpWorkerRequest 或 SimpleWorkerRequest 类派生的类中调用 ProcessRequest 方法。

 

我们按编号再来看一下这幅图中的数据是如何流动的。具体的请看下文。

  •  HttpRuntime将请求转交给 HttpApplicationFactory。HttpApplicationFactory(HttpApplicantFactory工厂)创建HttpApplication(为什么要用工厂?请参考:http://www.cnblogs.com/whtydn/archive/2009/10/16/1584584.html)。
  • 接下来请求通过一系列Module。
  • 请求经过所有的Module之后,流转到Handler进一步处理。
  • Handler处理完以后,请求再一次回到Module,此时Module可以做一些某个工作已经完成了之后的事情。

 4.HttpApplication对象分配给请求

 在添加所有事件处理程序模块之后执行自定义初始化代码。)。

下面的关系图说明了这种关系:

 那SessionStateModule是什么呢? 怎么样配置自定义的IhttpModule呢?

http://www.cnblogs.com/JimmyZhang/archive/2007/11/25/971878.html)

 关于Module请参考:http://www.cnblogs.com/anlen/articles/3613186.html
 MSDN:http://msdn.microsoft.com/zh-cn/library/system.web.ihttpmodule(v=vs.100).aspx

 关于Handler请参考:http://www.cnblogs.com/anlen/articles/3613204.html

MSDN:http://msdn.microsoft.com/zh-cn/library/system.web.ihttphandler(v=vs.110).aspx

通过HttpApplicationFactory创建了一个HttpApplicant对象,负责处理整个请求,是 类的实例启动应用程序。

5.由HttpApplication管线处理请求

  类的开发人员需要注意这些事件。

 脚本侵入概述

 节中配置了任何 URL,则执行 URL 映射。

 事件。

此事件始终被引发,并且始终是请求处理期间发生的第一个事件。

 事件。

 事件可确保在处理附加模块或事件处理程序之前对请求进行身份验证。

 事件。

预订 PostAuthenticateRequest 事件的功能可以访问由PostAuthenticateRequest 处理的任何数据。

 事件。

订阅 AuthorizeRequest 事件可确保在处理附加的模块或事件处理程序之前对请求进行身份验证和授权。

 事件。

订阅 PostAuthorizeRequest 事件可确保在处理附加的模块或处理程序之前对请求进行身份验证和授权。

 事件。

在 ASP.NET 完成授权事件以使缓存模块从缓存中为请求提供服务后发生,从而绕过事件处理程序(例如某个页或 XML Web services)的执行。

 事件。

执行并允许缓存模块满足来自缓存的请求时发生。

 类派生的对象(页),并且需要对该页进行编译,则 ASP.NET 会在创建该页的实例之前对其进行编译。

 事件。

在 ASP.NET 已将当前请求映射到相应的事件处理程序时发生。

 事件。

事件在创建了事件处理程序之后引发。

 事件。

 处理的任何数据。

 事件。

恰好在 ASP.NET 开始执行事件处理程序(例如,某页或某个 XML Web services)前发生。

例如,如果该请求针对某页,则当前的页实例将处理该请求。

 事件。

在 ASP.NET 已将当前请求映射到相应的事件处理程序时发生。

 事件。

在 ASP.NET 已将当前请求映射到相应的事件处理程序时发生。

 事件。

在 ASP.NET 已完成所有请求事件处理程序的执行并且请求状态数据已存储时发生。

 属性,则执行响应筛选。

 事件。

当 ASP.NET 执行完事件处理程序以使缓存模块存储将用于从缓存为后续请求提供服务的响应时发生。

 事件。

在 ASP.NET 完成缓存模块的更新并存储了用于从缓存中为后续请求提供服务的响应后,发生此事件。

 事件。

 事件。

恰好在 ASP.NET 向客户端发送 HTTP 标头之前发生。

 事件。

恰好在 ASP.NET 向客户端发送内容之前发生。PreSendRequestContent 事件可能发生多次。

  IIS6中共有24个事件,其中有19个事件是我们可以进行控制的。因为这些都是事件,所以可以往里面添加多个自定义方法。通常说的事件是从BeginRequest开始的。先通过一张图来了解下这些事件是在什么地方执行的。

 

BeginRequest、AuthenticateRequest、AuthorizeRequest、ResolveRequestCache、AcquireRequestState和PreRequestHandlerExecute。(ps:HttpModule不只是一个,这六个可在Application中控制)。

H:执行Handler中的PracessRequest()。(ps:Handler也不止一个)。

Unload。你可以记住单词SILVER来记这些事件,S-Start(没有任何意义,仅仅是为了形成一个单词),I(Init)、L(Load)、V(Validate)、E(Event)、R(Render)。其实还是HttpHandler中的事件。

PostRequestHandlerExecute、PostRequestState、UpdateRequestCache、EndRequest。

添加方法如下:

),ASP.NET 可在 Global.asax 文件中将应用程序事件自动绑定到处理程序。(为什么可以在Global.asax中添加方法?因为Global.asax与HttpApplication是继承关系。)。此处能添加的事件有19个,如下图所示:


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
ASP.NETCore基本项目目录结构-ASP.NETCore基础教程-简单教程,简单编程 ...发布时间:2022-07-10
下一篇:
ASP.NETMVC-MvcPager发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap