想要学好控件开发是一件不容易的事,要了解的知识面也很广。
而想要开发一个好的组件则比控件更难,一个好的组件开发是对技术和经验的累计过程。
面试的时候见过这样的人,说自己的能力是熟练开发Web控件及组件,有N年的工作经验,等等,但我问及其asp.net页面生存周期,他反问我说那个是什么,和控件开发有什么关系,无语中。。。。。。
类似的例子很多,我就不一一而言了,对于一个普通的asp.net程序员都应该充分了解的asp.net页面对象模型以及其生存周期和执行的各个阶段,对于控件开发人员来说这个就更应该是自己知识库的一部份、很重要的一部份,我很怀疑这个都不是很清楚的控件开发人员,是否有资格称自己是一个asp.net控件开发人员。
因此,在加入博客园“控件开发团队”之际,我借花献佛,把asp.net的页面对象模型抖出来,抛砖引玉,希望大家指正:(节选自http://www.microsoft.com/china/MSDN/library/WebServices/ASP.NET/TheASP.NETPageObjectModel.mspx)
页面生存周期
一旦完全确定 HTTP 页面处理程序类,ASP.NET 运行时就调用该处理程序的 ProcessRequest 方法以处理请求。通常情况下,无需更改此方法的实现方式,因为它是由 Page 类提供的。
此实现方法一开始就调用 FrameworkInitialize 方法,以此建立页面的控件树。此方法是 TemplateControl 类(Page 类本身就是从该类派生出来的)的一个受保护的虚拟成员。任何针对 .aspx 资源而动态生成的处理程序都重写 FrameworkInitialize。在此方法中,该页面的完整控件树得以构建。
接下来,ProcessRequest 使该页面经历若干阶段:初始化,加载视图状态信息和回发数据,加载页面的用户代码并执行回发服务器端事件。随后,该页面进入呈现模式:收集更新后的视图状态;生成 HTML 代码然后将其发送到输出控制台。最后,卸载页面,并认为已完成对该请求的处理。
在各个阶段中,页面都会激发一些 Web 控件和用户定义的代码所能截获并处理的事件。其中的一些事件是嵌入式控件专用的,因而并不能在 .aspx 代码级进行处理。
如果页面想要处理某个事件,它应该显式地注册相应的处理程序。然而,为了向后兼容早期的 Visual Basic 编程风格,ASP.NET 也支持一种隐式的事件挂起形式。在默认情况下,页面将尝试把特定的方法名与事件匹配起来;如果找到匹配的方法,就认为该方法是该事件的处理程序。ASP.NET 提供了六个方法名的特定识别。它们是 Page_Init、Page_Load、Page_DataBind、Page_PreRender 和 Page_Unload。这些方法被当作是 Page 类所提供的相应事件的处理程序。HTTP 运行时将自动把这些方法与页面事件绑定起来,这样一来,开发人员就不必编写所需的粘接代码。例如,名为 Page_Load 的方法与页面的 Load 事件绑定,就像已编写以下代码一样。
this.Load += new EventHandler(this.Page_Load);
这种自动识别特殊名称的功能由 @Page 指令的 AutoEventWireup 属性控制。如果将该属性设置为 false,则任何想要处理某个事件的应用程序都需显式地连接到该页面事件。如果页面不使用自动事件关联功能,就不必进行额外的操作以匹配各名称和事件,从而其性能也稍有提升。应该注意的是,所有的 Microsoft Visual Studio.NET 项目在创建时都禁用了 AutoEventWireup 属性。然而,此属性的默认设置为 true,意味着诸如 Page_Load 等方法会被识别并被绑定到相关的事件。
页面的执行过程包括下面表格中所列的一系列阶段,并以具有一些应用程序级事件和/或受保护且可重写的方法为特征。
表格 1. ASP.NET 页面生存周期中的关键事件
阶段 | 页面事件 | 可重写方法 |
页面初始化 |
Init |
|
加载视图状态 |
LoadViewState | |
处理回发数据 |
实现 IPostBackDataHandler 接口的任何控件中的 LoadPostData 方法 | |
加载页面 |
Load |
|
回发更改通知 |
实现 IPostBackDataHandler 接口的任何控件中的 RaisePostDataChangedEvent 方法 | |
处理回发事件 |
控件所定义的任何回发事件 |
实现了 IPostBackEventHandler 接口的任何控件的 RaisePostBackEvent 方法 |
页面呈现前阶段 |
PreRender |
|
保存视图状态 |
SaveViewState | |
呈现页面 |
Render | |
卸载页面 |
Unload |
在页面级上,以上所列的某些阶段是不可见的,并仅影响服务器控件编写者和那些凑巧要创建从 Page 派生的类的开发人员。页面向外界发送的活动信号仅包括 Init、Load、PreRender、Unload 以及嵌入式控件所定义的所有回发事件。