一、ASP.Net Web应用程序中的请求处理过程
二、 http模块生命周期:
三、Asp.NET页面生命周期
1、阶段
阶段 | 说明 |
请求页面(Page Request) | 严格地说,这个阶段不是页面生命周期的一部分。而是页面生命周期之前的一个阶段。Asp.NET接收到一个页面请求之后,执行分析和编译页面的工作或者从缓存中取出该页面发送给客户端。 |
开始(Start) | 在这个阶段,Asp.NET设置Page对象的Request和Response属性;确定该页面请求是否为PostBack;给页面设置UICulture属性。 |
初始化(Initialization) | 页面和控件对象的初始化;为控件设置UniqueID;为页面设置Master Page和Theme;需要特别注意的是,在这个阶段,客户端提交的数据,还没有被恢复到页面控件中去,包括ViewState在内。 |
加载(Load) | 加载ViewState; 将表单数据设置到对应控件中去。 |
回发事件(PostBack event) | 如果当前请求是一个PostBack请求,那么必然有某个事情导致了这次PostBack, 现在就到了执行该事件在服务器上的Event Handler的时候了。 这个阶段主要的问题在于Validation和Event Handler的执行次序。 1.如果该Event本身没有直接导致Validation, 比如我在Button上设置了不需要Validation,那么该Button的Click Event Handler先执行,然后页面上会执行页面上所有Validator 控件的Validator方法,然后设置页面的IsValid属性。 2.如果该Event本身直接导致了Validation,比如用户点击了一个Button,这个Button默认就会导致Validator被调用。这时候,Validation的执行是在Button的Click Event Handler之前的。等你进入Button的Click Event Handler的时候,页面的IsValid属性已经设置好了。 |
渲染(Rendering) | Asp.NET将页面和所有控件的ViewState保存到Form表单中去。然后调用所有控件和页面的Render方法来输出Html. |
卸载(Unload) | 执行到这个阶段的时候,页面已经将Html输出到客户端了。这个阶段要做的事情就包括:卸载Request对象和Response对象,执行一些清理工作。 |
2、页面中事件/阶段的执行模式:
事件&方法 | Page ONLY | Control ONLY | 顶层到底层 | 顶层到顶层 |
PreInit | YES | —— | ||
Init | 事件 | YES | ||
InitComplete | YES | —— | ||
LoadViewState | 方法 | YES | ||
ProcessPostData | 方法 | YES | ||
PreLoad | YES | —— | ||
Load | 事件 | YES | ||
PostBack Event | YES | —— | ||
LoadComplete | YES | —— | ||
PreRender | 事件 | YES | ||
DataBinding Event | YES | —— | ||
PreRenderComplete | YES | —— | ||
SaveViewState | 方法 | YES | ||
SaveStateComplete | YES | —— | ||
Render | 方法 | YES | ||
Unload | 事件 | YES |
3、示例程序
public partial class _Default : System.Web.UI.Page { protected int i = 1; protected void Page_PreInit(object sender, EventArgs e) { Response.Write(i + ".PreInit:当页面初始化开始时发生"); i++; Response.Write("<br>"); } protected void Page_Init(object sender, EventArgs e) { Response.Write(i + ".Init:当服务器空间初始化时发生"); i++; Response.Write("<br>"); } protected void Page_InitComplete(object sender, EventArgs e) { Response.Write(i + ".InitComplete:当页初始化完成时发生"); i++; Response.Write("<br>"); } protected void Page_PreLoad(object sender, EventArgs e) { Response.Write(i + ".PreLoad:当页load事件前发生"); i++; Response.Write("<br>"); } protected void Page_Load(object sender, EventArgs e) { Response.Write(i + ".Load:当服务器控件加载到Page对象中时发生(加载页面时)"); i++; Response.Write("<br>"); //在Load和LoadComplete之间会执行控件事件. //如 Button 控件的 Click 事件或 TextBox 控件的 TextChanged 事件。 } protected void Page_LoadComplete(object sender, EventArgs e) { Response.Write(i + ".LoadComplete:当页面生命周期的加载阶段结束时发生"); i++; Response.Write("<br>"); } protected void Page_PreRender(object sender, EventArgs e) { Response.Write(i + ".PreRender:当页加载控件之后,呈现之前发生,使用该事件对页或其控件的内容进行最后更改(预呈现)"); i++; Response.Write("<br>"); } protected void Page_PreRenderComplete(object sender, EventArgs e) { Response.Write(i + ".PreRenderComplete:呈现内容前发生.(预呈现完成)"); i++; Response.Write("<br>"); } protected void Page_SaveStateComplete(object sender, EventArgs e) { /*网页上控件的状态信息是在 PreRenderComplete 事件后保存的。 在SaveStateComplete事件之前用Trace查看页时其实在该事件前还有 一个SaveState事件,只是这里无法演示. 注意:SaveStateComplete 事件在将页和页上控件的视图状态和控件状态保存到持久性介质之后引发。 这是在页被呈现到请求浏览器之前引发的最后一个事件。*/ Response.Write(i + ".SaveStateComplete:在页已完成对页和页上控件的所有视图状态和控件状态信息的保存后发生."); i++; Response.Write("<br>"); /*最后一部操作 呈现:Render: 它不是事件;在处理的这个阶段,Page 对象会在每个控件上调用此方法Render()。 所有 ASP.NET Web 服务器控件都有一个用于写出发送给浏览器的控件标记的 Render 方法。*/ /*当你关闭页面的时候就会引发UnLoad(当服务器控件从内存中卸载时发生) 和Disposed两事件(当从内存释放服务器控件时发生,这是服务器控件生存期的最后阶段) 首先加载UnLoad事件:卸载页面:完全呈现页、将页发送至客户端并准备丢弃时, 将调用卸载。此时,将卸载页属性(如Response和Request)并执行清理. 最后加载Disposed事件,释放资源,生命周期结束.... */ } }
结果显示:
四、PageLoad 与 OnLoad区别:
1、用VS.Net生成的页面中的Page_Load方法(事件处理程序)就是响应Page.Load事件的。对于每一次请求,Load事件都会触发,Page_Load方法就会执行。
2、@Page指令中的AutoEventWireup=true时,页面会与某些特殊的事件方法绑定,自动识别这些具有特定名称的事件。这些特定名称包括:Page_Init, Page_Load, Page_DataBind, Page_PreRender和Page_Unload等。asp.net不需要显示的来绑定事件处理程序,它会在运行时自动的根据他们的方法名和签名绑定事件,对每一个事件,ASP.NET会根据Page_eventname这种模式去搜寻方法,如果没有找到带此签名的事件处理程序,则 ASP.NET 将检查没有参数的重载。
当时AutoEventWireup=false的时候,则必须显示绑定事件方法,比如,你有一个Page_Load方法,只有当你这样写代码的时候,才会触发事件方法:Page.Load += Page_Load;在这种情况下,方法名称不必遵循某一模式。
3、Page.Load事件是在System.Web.UI.Control类中定义的(此类是Page和所有服务器控件的基类),是在OnLoad方法中触发Page.Load事件。
因此如果在Page页面里重写了OnLoad方法,则此时虽然是用的AutoEventWireup=true,但Page_Load方法也不会被执行。如果比较考虑性能,建议用override Oneventname方法的方式来实现页面的事件加载。
public partial class Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("2");
}
protected override void OnLoad(EventArgs e)
{
Response.Write("1");
base.OnLoad(e);
Response.Write("3");
}
}
输出123。首先由于override父类的OnLoad,所以先执行页面的OnLoad方法,输出1,然后执行父类的OnLoad方法,一直上推到执行完Control类的OnLoad方法后,执行Load事件的委托链方法,执行Page_Load方法,输出2。最后回到
页面的OnLoad方法输出3。如果AutoEventWireup=false,则Page_Load不执行。
五、总结:三张图片详解Asp.Net 全生命周期还不错。
1、 第一张图片从全局说明从客户端发出一个Request请求,服务器windows内核中的HTTP.SYS组件接收该请求开始到IIS处理完该请求并响应到客户端结束。
2、 第二张图片为图1中Http处理管线的详细步骤
3、 第三张图片为图2Http处理管线中调用处理程序(HttpHandler, 此处为Page对象)的详细生命周期过程。