参考:http://msdn.microsoft.com/zh-cn/library/ms178472%28v=vs.100%29.aspx
http://msdn.microsoft.com/zh-cn/library/aa479007.aspx#XSLTsection124121120120
写点文章,训练下自己。没说清楚的还望见谅。希望你看下参考的内容。
请参考上一篇:Asp.net的生命周期之应用程序生命周期
用户请求
从 用户角度来说,我不管你后台经历了什么,我只想要我请求的页面。请求到服务器端,服务器必须得有所表示的是吧,即使不想搭理人家也得让IIS给人家说声:找不到服务器。请求来到服务器端,肯定要让服务器知道你的信息(就像见到另一个人时,看到的身高,脸型等等),然后把你的请求目的告知服务器,知道你的目的后快速地把你的事办好。说起来,感觉服务器就像一个很会服务的商场,你(说的是请求)来了这,服务器招待好你,尽量给你想要的,走时保证把你送到家,同时会开张证明给你,对你说:“下次来时给你打折”,当你再来时他会缩短你拿东西的时间。当然招待时,就像你去买条1.7m的裤子,这家商场可能需要在仓库里从裤头开始找起,直到找到或者找完所有东西才能给你结果,当然,这是是费了好多功夫的。
请求道服务器端就得经过一个周期,一个找的周期或者重新做一个的周期。Asp.net的页面一般是动态的,而在客户端则是静态的(.aspx后缀的页面可以看做是静态的,.cs页面才是动态的,单页开发模式中的C#代码也是在后台执行的),Asp.Net页面周期说白了就是:找到这个页面(判断有木有),接着把动态的内容合到静态页面种,生成的静态页面由IIS交给用户。生成的页面,通过查看页面的源代码时,会发现请求的页面没有Asp控件,Asp控件也都变成Html控件或者Html服务器控件。Asp.Net的动态体现在绑定数据和处理数据上,而不像Html页面是一个固定的。
网上经常看到请求页面的后缀名是Html页面是怎么回事?这些页面都是静态的吗?
首先说一点网页开发语言不止只有asp.net,像Java等语言也可以做网页开发。这些网页看上去是静态的,实际上这些界面大部分还是动态,它们只是用了伪静态。说真的生成大量的Html页面也是有可能的,有的页面就几k 而已,存起来也不失是一种方法。
从 技术来说,每个请求都是无状态的。浏览器和服务器通信时会建立TCP链接,连接通后服务器从浏览器发来的请求报文中读取请求信息,知道浏览器要什么,然后 根据这些信息去"拿"相关数据,拿到数据后发给浏览器,然后关闭TCP连接。说白了,就是浏览器知道服务器在哪,知道找谁要数据,服务器只知道你要的是什么,怎么给你,数据给浏览器发过去后就关闭连接。服务器经过生命周期后发给浏览器的是一个新的页面。从用户来角度来说,我不管你发的是什么,我只要知道 我请求的数据过来了,浏览器显示出来即可。查看IIS协议你会发现会有关闭连接的报文。
当然这种无状态的请求是无法被人接受的,例如:登陆一个系统,难道每次请求你这个系统下的页面时,我都要重新登陆吗?这时就需 要一种解决方案来解决这种无状态通信,而微软为我们提供了这种会话机制。这种机制并不陌生,就是常见的如Cookie、ViewState、Session、数据库等。当然这种机制是包含在页的生命周期中的。
那服务器怎么知道我是第N次请求?
请求也是分第一次和回发请求的,判断回发最常见的属性就是IsPostBack, 而判断IsPostBack的依据就是ViewState。页面第一次请求通常会产生一个ViewState,再次回发时系统就根据是否有ViewState来判断是否是第一次提交。不论是触发事件,还是提交数据,通常都是Post方式提交,这种方式也罢ViewState提交到服务器。ViewState产生的条件是,只要<Form>表单中有Runat=server属性,就会产生它。这里说的当然不包含Ajax请求和别的特殊方式,说的只是普通页面。
那么浏览器是怎么和服务器通信呢?服务器是怎么知道用户点击那些控件,触发那些事件呢?
答案还是和ViewState有关。通过Post提交的ViewState提交的据,数据提交到服务器后。服务器会在LoadAllState()中获取_VIEWSTATE的值,如果有值则进行反base64编译和反序列化,获取到对象的键值对,重新存入页面类的ViewState属性中。提交到服务器的信息一般都要有ViewState,这里面包含了触发的事件信息,控件的状态的等一堆信息。在页面后半部分会有一个SaveAllState()方法来京页面中的ViewState属性进行序列化和base64编码,添加到一个_VIEWSTATE隐藏域中并添加到html代码中。当然这些信息是通过一系列事件重新组装后发给用户的。
禁用ViewState的结果:我们采用ListView控件在第一次请求时绑定数据,并在页面禁用ViewState,你会发现控件是没有数据的,没有禁用的情况下控件中会有数据的。这也是为什么浏览器中一个普通的页面经过处理后,还会有先前的数据,要知道每次请求发来的都一个新的页面。刷新尚且如此,更何况回传页面呢?
页面的状况
Asp.Net是允许你在页面中写C#代码。而前台与后台的关系是,前台继承于后台。页面中是可以编写C#代码的。
1.当页面上没有包含任何服务器端语言的时候(<%%>、 runat="server"),整个页面作为 文本资源供程序集使用。说白了,就是当做一堆字符串处理。
2.当页面中包含 <%%>和html代码字符串时,当前前台页面类里会自动生成一个
方法,这个方法中 向一个写出器对象里 写入页面的html代码,和执行
<%%>内的内容。
3当页面中既包含<%%>、html代码字符、runat=server的html、服务器控件标签时,那么前台页面类会为每个runatserver的控件都创建一个方法,并通过 buildControlTree方法来组织各个控件的依赖(包含)关系
页面的组成
一个页面的组成离不了控件,而这些控件可由三种控件组成。
1.html控件标签,在服务端其实就是字符串,不会有任何语义处理。
2.带runat="server"属性的
html标签,那么在编网站译程序集的时候,后台类里就会自动创建一个 protected 修饰的服务器控件类的对象。(protected
HtmlGenericControl divMsg;)
HtmlGenericControl 主要对应 非表单控件的html标签。
protected HtmlGenericControl divMsg;
protected HtmlForm form1;
protected HtmlImage imgs;
protected HtmlGenericControl spanMsg;
protected string strName;
protected HtmlInputText txtName;
3 ASP服务器控件。例如<ASP:Button>,此种控件必须放在runat=server的form中。生成的一个Button类。
由于前台继承与后台的关系,所以在aspx类可以访问到这个带runat=server控件,并且在cs类里也可以访问到这个类。控件变量里面包含一个Render方法,专门用来根据当前控件的响应的属性,生成对应的html标签字符串。
Response.Write(“字符串”),传入的数据都保存在哪呢?
每当调用Response.Write方法“输出”响应报文体字符串的时候,其实就是将所有的输出自如都存入Response里的write对象的char数组里。
页的生命周期
在进入管道的第十一和第十二个事件时,就进入页的生命周期。页的生命周期说起来也就是出始化、实例化控件、还原和维护状态、运行事件处理程序代码以及进行呈现。当然这些请求页面的后缀是由交由Asp_Net运行环境处理的。这里说的生命周期以.aspx为主,毕竟.ashx页面简化了很多操作。
.aspx页是继承了page类的,而page是继承IhttpHandler接口了的。也就是说在管线中第八个事件就开始准备了,准备时只是把页面类对象转换成IhttpHandler接口,在第十一和第十二个事件之间才开始根据接口执行这些事件。而我们要知道IhttpHandler接口中定义了两个方法,一个做判断,另一个ProcessRequest方法,而入口恰恰就是这个ProcessRequest方法。
在调用接口对象的ProcessRequest方法时,会调用父类的ProcessRequest方法,在此方法中,父类调用了FrameworkInitialize方法,由于父类被页面类重写了,所以执行的是当前页面类的FrameworkInitialize方法。在执行这个方法时,会调用_buildControlTree(注:控件构造数)方法。控件构造数的方法执行后,将调用ProcessRequestMain方法,在此方法里将执行整个页面的生命周期。
具体的是
几个重要的事件:
- LoadState-将表单隐藏域_VIEWSTATE里的数据设置到页面对象ViewState属性中。
- ProcessPostData-将表单里提交的控件数据设置给页面对象的控件树中的控件的属性。
- PageLoad-调用程序员在后台的Page_Load中编写的代码,此时程序员可以通过访问控件属性的方式获得浏览器提交的表单控件值了。
- ProcessPostDataSecond-为在Page_Load中添加的新控件赋值(值来自表单提交的数据)
- RaiseChangedEvents-执行控件非点击回传事件。
- RaisePostBackEvent-执行控件点击回传事件。
- SaveState-将控件的属性状态存入页面的ViewState中
- Render-递归调用控件树里每个控件的Render来生成整个页面的Html代码——存在于Response。
下面的事具体的事件
流程图
事件里有回传事件,页面本来就有的事件和控件事件三种。
回传图
参考:http://www.cnblogs.com/zhaoyang/archive/2011/11/16/2251200.html三张图说明生命周期