第3章ASP.NET页面剖析
在Web应用程序上下文中,ASP.NET页面会在第一次被请求时,按需被动态编译。动态编译并不是A SP.NET页面(.aspx文件)特有的,还发生在.NET Web服务(.asmx文件)、Web用户控件(.ascx文件)、HTTP处理程序(.ashx文件),以及其他几种ASP.NET应用程序文件(如global.asax文件)身上。运行时管道模型负责处理输入的(incoming)HTTP数据包,使其从一个简单的特定协议有效负载转化为服务器端ASP.NET对象——准确地说,是一个系统Page类的派生类的实例。ASP.NET中的HTTP运行库会处理页面对象,将生成的标记插入响应序列中。处理用户代码的若干事件标志着响应序列的生成各个阶段,整个过程称为“页面的生命周期”(page life cycle)。
本章会介绍如何将.aspx页面的HTTP请求映射为页面对象、Page类的编程接口,以及如何通过页面生命周期中的事件处理控制标记的生成。
3.1  页面的调用
先让我们具体认识一下.aspx页面是如何被转化为类并编译为程序集的。特定.aspx资源的程序集的生成,分为两个步骤进行。首先,该资源文件的源代码会被解析,根据得到的信息,从Page类(或P age的派生类)派生出相应的类。然后,动态生成的类会被编译为程序集,该程序集之后会被缓存到A SP.NET专用的临时目录下。
只要链接的(linked).aspx源文件没有被更改,且整个应用程序没有重启,已编译的页面就一直存在。对已链接的.aspx文件的任何更改,将使相关程序集变为无效,并在该页面下一次被请求时,强制HTTP运行库创建新的程序集。【89】
提示:编辑fig和global.asax之类的文件会导致整个应用程序重启。在这种情况下,在某个页面被请求时,所有页面会被重新编译。如果Bin文件夹中的程序集被改动(新建或被替换),所有页面也会被重新编译。
3.1.1  运行机制
能够通过基于Internet信息服务(IIS)的Web服务器访问的所有资源,会按扩展名进行组织。任何来访的请求会被分配给特定的运行时进程模块进行实际的处理。IIS上下文中能够处理Web资源的模块是Internet服务器应用程序编程接口(ISAPI)扩展——实际是普通的传统Win32动态链接库(DLL),很像接口,通过预定义的名称和原型,向外暴露了许多API函数。IIS和ISAPI扩展会针对专用的通信协议使用这些DLL入口方法。当IIS需要ISAPI扩展完成某项任务时,它会在是加载相应的DLL,并通过有效参数调用适当的函数。虽然ISAPI文档没有指出ISAPI为接口,但它的确是实现了一组公共编程接口的模块。
当某个资源的请求到达时,IIS首先会判断所请求的资源类型。静态资源(如图像、文本文件、HTML 页
面和非脚本ASP页面)直接由IIS处理,而不调用任何外部模块。IIS在本地Web服务器上访问被请求的文件,并将其内容写入输出控制台,这样,发出请求的浏览器便能够接收到它了。需要在服务器端处理的请求会被传到已注册的模块中。例如,ASP页面会由名为asp.dll的ISAPI扩展处理。一般而言,当资源与可执行代码关联时,IIS会将请求交给可执行代码做进一步处理。带.aspx扩展名的ISAPI扩展会被分配给aspnet_isapi.dll(如图3.1所示)。
图3.1  带.aspx扩展名的资源的IIS应用程序映射【90】资源映射信息存储在IIS元库(一种IIS专用的配置数据库)中。ASP.NET在安装时对IIS元库进行修改,使aspnet_isapi.dll能够处理某些典型的ASP.NET资源。表3.1列出了其中的一些。
表3.1  as pnet_isapi.dll的IIS应用程序映射
此外,aspnet_isapi.dll扩展还能够处理其他Microsoft Visual Studio典型扩展名(如.cs、.cspr oj、.vb、.vbproj、.config和.resx)。
正如第1章所述,ASP.NET ISAPI扩展的具体行为取决于应用程序所选择的进程模型。下面将给出其中的两种。
IIS 5.0进程模型
如果将ASP.NET应用程序部署到Windows Server 2003之前任何一个版本的系统中,就只能选择IIS  5.0进程模型。根据该进程模型的策略,aspnet_isapi.dll不处理.aspx文件,而是充当调度程序。它将收
集有关被调URL和底层资源的所有信息,并将其发送给另一个特殊进程——名为aspnet_wp.e xe的ASP.NET工作进程。ISAPI扩展与工作进程之间的通信是通过命名管道(named pipe)完成的。
整个模型如图3.2所示。【91】
工作进程的一个副本始终运行,并承托所有活动的Web应用程序。但在Web服务器使用多个CPU时,情况则不同。如果这样,可以对ASP.NET运行库进行配置,允许多个工作进程运行,每个进程对应一个可用CPU。一台服务器的多个CPU上运行多个进程,这样的模型称为“网络园”(web garden),可通过fig文件的<processModel>区段控制。
当单一工作线程被所有CPU使用,并控制所有Web应用程序时,并不一定表示没有实施进程隔离。事实上,每个Web应用程序是通过其虚拟目录标识的,分别从属于独立的应用程序域(通常称为AppDomain)。当某个虚拟目录被客户端第一次请求时,ASP.NET工作进程会创建一个新的AppDomain。之后,ASP.NET运行库将加载所有所需的程序集,并将控制权交给托管(hosted)HTTP管道,后者将对该请求做实际的处理。【92】
如果客户端请求的是一个已在运行的Web应用程序,ASP.NET运行库只是将该请求转发给与其虚拟目录相关联的现有AppDomain。如果处理当前页面的程序集没有被该AppDomain加载,则动态创建它;如果在第一次调用时已经被创建,则直接使用。
图3.2  基于IIS 5.0进程模型的ASP.NET运行时环境
IIS 6.0进程模型
如果Web服务器的操作系统是Windows Server 2003或更高版本,IIS 6.0进程模型是ASP.NET的默认选择。该进程模型的名称已明确指出,该模型需要IIS 6.0。然而,在Windows Server 2003计算机上,
仍可以使ASP.NET按IIS 5.0的方式工作。如果要这样做,可以通过更改fig的< processModel >区段,显式地启用该模型:
<processModel enable="true">
注意,我们不提倡切换到过去的IIS 5.0进程模型(虽然这样做并没有错)。主要原因在于,IIS 6.0
使用的是一种不同的内核模块管道来处理入站请求,只有在仿真模式下工作才能模仿IIS 5.0的行为。IIS 6.0管道以一种名为的工作进程为中心。该可执行程序的副本由分配给同一应用程序
asp 源代码
池的所有Web应用程序共享。用IIS 6.0的术语来讲,应用程序池是共享同一工作线程副本的一组W eb应用程序。IIS 6.0使我们能够对应用程序池进行定制,以达到托管于Web服务器的各种应用程序所需的隔离程度。
<工作进程会加载aspnet_isapi.dll,随后,ISAPI扩展加载公共语言运行时(CLR),启动A SP.NET运行时管道,对请求进行处理。若使用IIS 6.0进程模型,ASP.NET内建的工作进程便会被禁用。
提示:只有ASP.NET 1.1和更高版本能够充分利用IIS 6.0进程模型。如果在Windows                              Server 2003计算机上安装ASP.NET 1.0,那么选择默认设置IIS 5.0进程模型。之所以会这样,是因
为只有ASP.NET 1.1搭载的aspnet_isa pi.dll能够识别宿主,并在需要时加载CLR。而ASP.NET 1.0包含的aspnet_isapi.dll只能将请求发给ASP.NET工作进程,且不会加载CLR。
图3.3展示了IIS 6.0处理ASP.NET应用程序和其他Web应用程序的过程。【93】
图3.3  IIS 6.0中的ASP.NET应用程序和其他Web应用程序的处理过程
IIS 6.0以内核级模块的形式实现了其HTTP监听程序。因此,所有的输入(incoming)请求会首先被一个驱动程序(http.sys)管理。第三方代码不能与该监听程序进行交互。这样,即使用户模式出现问题,IIS的稳定性也不会受到影响。http.sys驱动程序会监听请求,并将其追加到相应的应用程序池请求队列中。一个叫“Web管理服务”(Web Administration Service,WAS)的模块会读取IIS元库,并指示h ttp.sys驱动程序创建请求队列,队列数量与元库中注册的应用程序池的数量一
致。【94】
总之,使用IIS 6.0进程模型,ASP.NET会运行得更快,因为(IIS 管理服务)与工作进程之间不需要进行任何进程间通信。HTTP请求直接投递给承托CLR的工作进程。此外,ASP.NET工作进程不是特殊的进程,而仅仅是IIS工作进程的副本。这样,回收进程、缓存页面和监视运行状况的负担会由IIS承受。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。