欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

IIS处理Asp.net请求和Asp.net页面生命周期说明

程序员文章站 2024-03-06 23:41:20
首先我们要弄清楚两个非常重要的概念: 1, worker process(w3wp.exe). worker process管理所有的来自客户端的请求并给出响应。它是iis...
首先我们要弄清楚两个非常重要的概念:
1, worker process(w3wp.exe). worker process管理所有的来自客户端的请求并给出响应。它是iis下asp.net应用程序的核心。
2, application pool. 它是worker process的容器,iis5及之前的iis版本均没有application pool的概念。每一个application pool对应着一个worker process,在iis metabase中维护着application pool和worker process的mapping。这就避免了iis5中出现的worker process(iis5中是aspnet_wp.exe,同一时间只能运行一个该进程)崩溃,application全崩溃的局面。
客户端向iis发出一个资源请求后发生了如下事情:
1, server接受该请求
iis6通过内核模式(kernel mode)中的http.sys来分发各个request到application pool。 这并不是随机的过程,在application pool创建的时候就已经注册到了http.sys,所以当请求来到时http.sys会直接发送到相应的application pool。 接下来在iis的用户模式(user mode)中,web admin services (was) 做了从http.sys中得到request并分发到application pool的工作。application pool直接把request传递给worker process。
2, 请求传递到worker process后,worker process初始化加载asp.net isapi(internet server application program interface),asp.net isapi进而加载clr创建托管环境。
(注:isapi只是一个接口,起到一个代理的作用,主要能力就是根据request url的后缀来寻找该后缀的处理程序)
asp.net isapi定义在aspnet_isapi.dll中,它本身运行在一个非托管的环境中。asp.net isapi开始一个httpruntime, httpruntime调用processrequest方法来开始处理请求。processrequest根据isapi传进来的iwrtype 来创建不同的httpworkerrequest,从而屏蔽了不同iis的差异。接下来processrequest方法创建了httpcontext,我们使用httpcontext.current来访问它。在httpruntime使用httpapplicationfactory创建了httpapplication对象(ihttphandler)以后,所有的请求都会在通过httpmodule后找到相应的httphandler进行处理。在httpapplicationfactory创建httpapplication之前,会查找config(web.config和machine.config)文件中注册的所有的httpmodule,并根据配置信息加载相应的assembly,通过reflection创建对应的httpmodule,并将这些module加到httpapplication 的_modulecollection filed中。我们对一个application的请求最终会落到一个httpapplication对象上。当一个请求到来时,asp.net会在httplication pool中查找未被使用的httpapplication对象。
3, 请求通过http管道后,每个请求都发向相关的各自的httphandler,iis请求处理过程结束。
httphandler是http管道的终点,它为每个request生成输出。system.web.ui.page就是这样一个典型的httphandler,当我们请求一个aspx页面,这个httphandler就生成html发送回客户端。看page类的签名:
public class page : templatecontrol, ihttphandler
{
}
可以看到,page类就是一个httphandler。
综上整个过程就是:当客户端向服务器发送资源请求时,请求首先到达iis的http.sys。然后http.sys发送请求道对应的application pool。 然后application pool发送请求到worker process(w3wp.exe)中加载isapi extension,isapi创建一个httpruntime对象来通过httpmodule和httphandler处理请求。 然后页面生命周期就开始了。
4, 页面生命周期开始
页面生命周期的主要阶段包括:
页面初始化(init): 服务器创建服务器控件的实例
加载(load): 控件实例被加载到它定义的页面对象中
预输出:(prerender) 对控件的更改被更新,准备输出。
保存(saveviewstate): 控件的状态信息被保存。
输出页面(render):服务器为控件创建html标记。
处理(dispose): 主要做的工作就是dispose, 关闭数据库连接,文件资源的释放等。
卸载(unload):销毁服务器控件的实例
页面生命周期的主要事件:
preinit:
1.检查ispostback 属性
2.动态设置master page
3.动态设置theme
4.设置控件的默认值(uniqueid等)
5.重新创建动态控件(初始化控件),初始化控件的值
init: 这个事件发生在所有的控件被初始化,所有的皮肤设置被应用以后。它用来读取或者初始化控件属性。它能够用来注册一些aspx页面中没有指出的控件的事件。
initcomplete: use this event for processing tasks that require all initialization to be complete.
preload: 加载页面的viewstate和所有的控件,然后处理所有的包含在request实例中的postback数据。
load: 这个事件可能是大家最熟悉的了。需要注意的是,page对象会递归的调用子控件的onload事件直到页面和所有的子控件被加载完成。这个事件主要用来设置控件属性的值,建立数据库连接(通常不这么做)。
control events: 这个就不多说了,主要是处理控件的事件,例如click。这也就让我们明白了每次我们click一个button的时候,实际上是要先去执行load事件然后才执行click事件的,一般我们用!ispostback来判断一下从而避免执行不必要的加载逻辑。
loadcomplete: 页面所有的控件都被加载以后执行,暂时没有想到用来干什么。。。
prerender: 在html被生成之前这是最后一个事件。每一个页面中的控件都有prerender的过程。在这里对将要输出的html结果进行最后一次修改。
savestatecomplete: 在这个时间发生之前,已经保存了所有控件和页面的,任何对page或者控件的改动都不会产生左右。暂时没想到用来干啥。
render: 它不是一个事件而是一个方法。工作就是把html写回客户端浏览器。
unload: 页面中的每一个控件都会发生这件事。在控件中,使用这个事件来做清理工作,例如关闭数据库连接等。对与页面本身也是做清理工作,例如关闭打开的文件和数据库连接,或者结束日志或者其它指定的工作。
需要说明的是,每次request都会创建一个全新的page类的实例,所以在页面中的自己定义的字段是不能在两次request中传递值的,需要使用viewstate来存储。
5, httphandler根据页面生命周期中事件的处理把结果发回iis,iis再把结果发回客户端浏览器。
值得注意的是,在这个过程中请求会再次通过httpmodule(注册一个endrequest事件)。
至此,整个request结束。