执行的各个阶段
页面生命周期中的第一个阶段是初始化。这个阶段的标志是 Init 事件。在成功创建页面的控件树后,将对应用程序触发此事件。换句话说,当 Init 事件发生时,.aspx 源文件中静态声明的所有控件都已实例化并采用各自的默认值。控件可以截取 Init 事件以初始化在传入的 Web 请求的生命周期内所需的所有设置。例如,这时控件可以加载外部模板文件或设置事件的处理程序。请注意,这时视图状态信息尚不可用。
初始化之后,页面框架将加载页面的视图状态。视图状态是名称/值对的集合,在此集合中,控件和页面本身存储了对所有 Web 请求都必须始终有效的全部信息。视图状态代表了页面的调用上下文。通常,它包含上次在服务器上处理页面时控件的状态。首次在会话中请求页面时,视图状态为空。默认情况下,视图状态存储在静默添加到页面的隐藏字段中,该字段的名称是 __VIEWSTATE。通过覆盖 LoadViewState 方法(Control 类的受保护、可覆盖方法),组件开发人员可以控制视图状态的存储方式以及视图状态的内容映射到内部状态的方式。
有些方法(如 LoadPageStateFromPersistenceMedium 以及其对应的 SavePageStateToPersistenceMedium),可以用来将视图状态加载并保存到其他存储介质(例如会话、数据库或服务器端文件)中。与 LoadViewState 不同,上述方法只能在从 Page 导出的类中使用。
存储视图状态之后,页面树中控件的状态与页面最后一次显示在浏览器中的状态相同。下一步是更新它们的状态以加入客户端的更改。处理回发数据阶段使控件有机会更新其状态,从而准确反映客户端相应的 HTML 元素的状态。例如,服务器的 TextBox 控件对应的 HTML 元素是 <input type=text>。在回发数据阶段,TextBox 控件将检索 <input> 标记的当前值,并使用该值来刷新自己内部的状态。每个控件都要从回发的数据中提取值并更新自己的部分属性。TextBox 控件将更新它的 Text 属性,而 CheckBox 控件将刷新它的 Checked 属性。服务器控件和 HTML 元素的对应关系可以通过二者的 ID 找到。
在处理回发数据阶段的最后,页面中的所有控件的状态都将使用客户端输入的更改来更新前一状态。这时,将对页面触发 Load 事件。
页面中可能会有一些控件,当其某个敏感属性在两个不同的请求中被修改时,需要完成特定的任务。例如,如果 TextBox 控件的文本在客户端被修改,则此控件将触发 TextChanged 事件。每个控件在其一个或多个属性被修改为客户端输入的值时都可以决定触发相应的事件。对于这些更改对其非常关键的控件,控件实现 IPostBackDataHandler 接口,此接口的 LoadPostData 方法是在 Load 事件后立即调用的。通过对 LoadPostData 方法进行编码,控件将验证自上次请求后是否发生了关键更改,并触发自己的更改事件。
页面生命周期中的关键事件是被调用以执行服务器端代码的事件,此代码与客户端触发的事件相关联。当用户单击按钮时,将回发页面。回发值的集合中包括启动整个操作的按钮的 ID。如果控件实现 IPostBackEventHandler 接口(如按钮和链接按钮),页面框架将调用 RaisePostBackEvent 方法。此方法的行为取决于控件的类型。就按钮和链接按钮而言,此方法将查找 Click 事件处理程序并运行相关的委托。
处理完回发事件之后,页面就可以显示了。这个阶段的标志是 PreRender 事件。控件可以利用这段时间来执行那些需要在保存视图状态和显示输出的前一刻执行的更新操作。下一个状态是 SaveViewState,在此状态中,所有控件和页面本身都将更新自己 ViewState 集合的内容。然后,将得到序列化、散列、Base64 编码的视图状态,而且此视图状态与隐藏字段 __VIEWSTATE 相关联。
通过覆盖 Render 方法可以改变各个控件的显示机制。此方法接受 HTML 书写器对象,并使用此对象来积累所有要为控件生成的 HTML 文本。Page 类的 Render 方法的默认实现包括对所有成员控件的递归调用。对于每个控件,页面都将调用 Render 方法,并缓存 HTML 输出。
页面生命中的最后一个标志是 Unload 事件,在页面对象消除之前发生。在此事件中,您应该释放所有可能占用的关键资源(例如文件、图形对象、数据库连接等)。
在此事件之后,也就是最后,浏览器接收 HTTP 响应数据包并显示页面。
小结 ASP.NET 页面对象模型因其事件机制而显得格外新颖独特。Web 页面由控件组成,这些控件既可以产生丰富的基于 HTML 的用户界面,又可以通过事件与用户交互。以前,在 Web 应用程序的上下文中设置事件模型是件有挑战性的工作。可我们惊奇的看到,客户端生成的事件可以由服务器端的代码来解决,而且只进行一些相应的修改后,此过程仍可以输出相同的 HTML 页面。
掌握这个模型对于了解页面生命周期的各个阶段,以及页面对象如何被 HTTP 运行时实例化并使用是非常重要的。
查看本文来源