webform运行原理
运行原理相同点:aspx和ashx运行机制差不多。
运行原理不同点:
1.执行事件管道的时候,在7,8个事件之间创建的是前台页面类对象,那后台类是什么时候创建的呢?由于aspx前台页面继承自后台,所以创建前台页面类时,后台就创建好了。
2.在第11、12事件之间,调用存放在remapHandler中的前台页面类对象的processRequest方法,会进行复杂的处理,也就是走页面生命周期。
webform页面生命周期
1.通过反编译,查看前台类代码
前台代码P01Index.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="P01Index.aspx.cs" Inherits="webSite.P01Index" %> <<%@ Import Namespace="webSite" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> <script runat="server"> public string GetValue(string inputstr) { return "你输入了:" + inputstr +" 已经被前台页面类同名方法覆盖 "; } </script> </head> <body> <form id="form1" runat="server"> <div> 查看当前前台页面被编译后的页面类所在的程序集:<%= this.GetType().Assembly.Location %><br /> Name= <%=Name %><br /> Age=<%= Age %> <br /> 调用非私有方法:<%= GetValue("八戒") %><br /> Name= <% Response.Write(Name); %> <% if (Age > 30) { Response.Write("超过30了"); } else { Response.Write("你还可以玩几年"); } string res = kits.GetInput("哈哈"); Response.Write("<br />"+res); %> </div> <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox> <asp:Button ID="Button1" runat="server" Text="Button" /> </form> </body> </html>
1.1 如何查看当前前台页面被编译后的页面类所在的程序集? this.GetType().Assembly.Location
2 前台页面中写的代码被编译到_Renderfrom1方法中
3 页面中的方法会编译成前台页面类中的方法
4.调用前台页面类对象的ProcessRequest方法,此方法会调用父类的ProcessRequest方法,在父类方法中,调用this.FrameworkInitialize();
4.1 FrameworkInitialize() 在页生成过程中根据页的声明性特性初始化控件树
4.2 创建控件树,_BuildControlTree()内部就是将整个页面控件树的结构创建好,如果是普通的C#代码,则被编译到一个方法体里
4.3 在父类方法中紧接着调用ProcessRequestMain方法,在此方法中,主要是触发一系列的事件
4.4 通过ViewState,决定是否是IsPostBack,即确定当前请求是否是回发,如果ViewState不为null,那么IsPostBack则为true
4.5 ProcessRequestMain方法
4.6 在ProcessRequestMain方法中,调用了this.PerformPreInit();
(1)触发PreInit事件
(2)将加载个性化信息和页主题(如果有),初始化母版页。
4.7 在ProcessRequestMain方法中,调用了this.InitRecursive(null);
(1) 调用基类的InitRecursive方法通过递归对子控件进行初始化, 比如: 生成控件ID,设置控件的Page属性。
(2) Init事件将会在此时被触发
4.8 this.OnInitComplete(EventArgs.Empty); InitComplete事件被被触发
4.9 this.LoadAllState();加载页面状态解析ViewState,将页面表单中的ViewState进行反Base64编码,反序列化,存在页面的ViewState属性中
4.10 this.ProcessPostData(this._requestValueCollection, true);将表单里提交过来的控件数据设置给页面对象的控件树中对应控件的属性
4.11 this.OnPreLoad(EventArgs.Empty); preLoad事件被调用
4.12 LoadRecursive()被调用,页面的Load事件先被触发,紧接着控件的Load事件被触发,Page_Load方法就是响应Load事件的方法,因此此时Page_Load方法会被执行
4.13 this.ProcessPostData(this._leftoverPostData, false); 为在Page_Load中添加的新控件赋值(值来自表单提交)
4.14 this.RaiseChangedEvents();执行控件非点击回传事件,例如页面中的DropDownlist
4.15 this.RaisePostBackEvent(this._requestValueCollection);执行控件点击回传事件,例如Button
4.16 this.OnLoadComplete(EventArgs.Empty);触发LoadComplete事件
4.17 this.PreRenderRecursiveInternal();PreRender事件被触发
4.18 this.PerformPreRenderComplete();PreRenderComplete事件被触发
4.19 this.SaveAllState();将控件的属性状态存入页面的ViewState中
4.20 this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));;递归调用控件树里的每个控件的Render来生成整个页面的html代码
最后,上一张完整的大图
参考资料
1.传智播客
2.http://www.knowsky.com/897396.html
3.http://www.3fwork.com/b101/000785MYM001797/