您的位置:首页 > 编程语言 > ASP

Asp.Net请求原理and页面生命周期

2013-03-13 17:53 197 查看
前天去面试,让我说下生命周期,本来之前就了解过,但是没说出来,被深深的鄙视了;今天弄了一上午,现在发到这分享一下,有什么错误请各位大牛们指出~~

昨天面试,又遇到这问题了... 然后说了半天,人家问我一用户控件的周期在哪执行,我想了半天,也没有想出来,回来只好再研究了..

请求的本页面Page-Load->用户自定义控件Page-Load->本页面渲染之前Page-PreRender 这样一个顺序

页面发送请求原理

浏览器将请求封装成Http请求报文发送到服务器; 服务器端HTTP.SYS内核驱动模块来接收,这个模块监听着80

端口. 它首先去访问注册表确定请求交给谁去处理.

将请求交给了IIS IIS中分为了两块

1. w3svc服务 .它是寄宿在svchost.exe进程里.主要负责将请求分发给具体的扩展程序. 具体分发给谁呢?

2.配置是在InetInfo这个进程里面. 这是iis的核心进程,这里放着IIS的元数据.

在这里.访问IIS核心进程,分析当前后缀的请求是静态还是动态.要交给哪个扩展来处理(.aspx;.ashx 动态的交给aspnet_isapi.dll处理).如果是静态的直接返回到HTTP.SYS 在浏览器中显示,如果是动态 ,交给一个aspnet_isapi.dll这个扩展处理 在IIS5中, 是aspnet_wp.exe;在IIS6中和7中,是w3wp.exe

每一个网站都跑在一个单独的工作进程里面,网站间是通过进程进行隔离的.(不同的网站跑在不同的进程里面,这个称为应用程序池技术)

而在IIS5中,只是有一个进程,它是通过应用程序域来隔离每个进程之间的关联;

如果是动态页面的话.w3svc服务将请求又交给了aspnet_isapi.dll这个扩展. 这个扩展负责启动aspnet runtime,负责创建aspnet运行环境.还负责将请求交给ISAPIRuntime的PR方法,也就是非托管和托管程序的入口

在ISAPIRuntime,这就可以看到之后的源代码了

1.ISAPIRuntime对象 它调用了它的一个.ProcessRequest(ecb)方法; ecb是一个操作系统的句柄,指向了当前请求的内存空间,可以通过此句柄来拿到当前请求的报文;通过ecb句柄,创建了一个HttpWorkRequest对象.此对象就是对Http请求报文做了一些简单的封装.也就是请求的报文头,报文体而已;

再一次的将请求给下面分发

分发给了HttpRuntime这个对象, 又调用了RrocessRequest(wr)方法;将ecb句柄创建的WorkRequest对象传进去.根据这个对象封装了一个HttpContext(请求上下文)

HttpContext中包括了HttpRequest(封装http请求),还有一个是 HttpResponse(封装了Http的响应)

并且HttpRuntime还根据HttpApplicationFactory工厂 获取一个HttpAplication对象

在这个工厂中,获取实例的时候,先去Applition池里去面去查看有没有空闲的HttpApplication对象.如果有直接返回,如果没有那么就先编译global文件生成一个HttpAppliction的派生类,然后根据这个派生类反射创建一个HttpAppliction类型实例并返回.

这个HttpAplication对象,调用了ProcessRequest(HttpContext context)执行19个管道事件,流动着的就是HttpContext上下文 context 这需要走23个步骤

在第8个事件中,根据请求的地址,创建一般处理程序或者是aspx页面类型,并转成IHttpHandler接口对象;

在第9个事件中,会接收浏览器发送过来的SessionId,并且根据此值到服务器的Session池中找到对应的session对象,先尝试将页面类对象转换成IRequiresSessionState接口对象,如果转换不成功,刚不加载Session对象,如果转换成功则 将它赋值给页面对象的Session属性;(Page.HttpContext.HttpSessionState)

(页面生命周期)

第一步:创建控件树

在11到12个事件中.执行页面类(一般处理程序)的ProcessRequest方法 ;先根据页面上的每个控件和我们写的静态标签把这些基本都创建好,现在还不是正式的创建,还没有把控件new出来,它在初使化的时候才new;

执行_BuildControlTree()这个方法;方法内部就是将整个页面控件创建好,普通的C#代则被编译到一个方法体里面;


第二步:

决定是否是IspostBack,确定当前请求是不是回发过来的;它通过ViewState实现的;只要ViewState不为null,那么就是回发过来的,结果就为true.


第三步:

初使化 PreInint()初使化之前的一个事件

Init() 实际初使化:就将控件树上的控件都new一个实例,并赋默认值; 方法内部是执行了一个递归初使化;

InitComplete() 初使化完成


第四步:

加载ViewState,加载页面的状态;解析隐藏域中的ViewState

这个解析完成之后,下一步:


第五步:

ProcessPostDate() : 处理回发数据

1:比较表单提交过来的数据和控件上原来的状态做对比,然后将需要触发改变事件的控件放到一个集合里面去等待触发.(当你需要改变了一个方本框的值,它会将改变之后的和之前的做对比,将改变之后的这个控件或标签添加到集合中,等待改变的事件触发);

2:将表单中的值赋值到控件上面去.


第六步:

页面加载

PreLoad()加载之前


Load 就是我们用的Page_Load()方法; 在这里我们可以拿到控件中的值

第七步:

在load之后,再一次执行ProcessPostData:第二次处理回发的数据; 为什么要第二次呢? 允许在当面Load中再次对值进行处理;再次将需要触发改变事件的控件放到集合中去; 这是在事件响应之前最后的机会:引发改变事件的地方;


第八步:

LoadComplete() 加载之后

触发改变控件的事件,


第九步:

触发PostBack回发控件的事件


第十步:

PreRend() 页面渲染之前的事件 (就是将服务器控件转换成html代码的过程)

在这个方法之前,是最后能修改我们发送给客户端响应内容的机会;


第十一步:

保存当前页面的状态(将需要保存状态的值放到ViewState中,也就是隐藏域)


第十二步:

页面渲染 再回到到第11和第12个事件


2.托管程序:aspnet runtime



下面是我用反编译查看了下它内部的执行顺序..

1:



2:



3:



4:



5:



6:



7:



8:



9:



10:



11:



12:



13:



14:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: