APP下载

用一个案例看懂ASP.NET页面处理流程

2018-12-10王雅新

科技视界 2018年21期
关键词:控件视图代码

王雅新

【摘 要】Web页面是asp.net应用程序的重要组成部分,理解页面生命周期中执行的一系列步骤对软件代码的设计和优化非常重要。文章通过对单选按钮功能调试的案例剖析,分析和演示了Web页面处理过程中几个重要的生命周期阶段对页面交互数据的影响以及相关的代码处理。

【关键词】案例;页面生命周期

中图分类号: TP393.092 文献标识码: A 文章编号: 2095-2457(2018)21-0071-002

DOI:10.19694/j.cnki.issn2095-2457.2018.21.032

【Abstract】Web Form are an important part of ASP.Net applications,and it is important to understand the sequence of steps that are executed in the Asp.Net Form life cycle for the design and optimization of software code.This paper analyzes and demonstrates the influence of several important life cycle stages of Web Form processing on page interaction data and relevant code processing through case analysis of the function debugging of radio buttons.

【Key words】Case;Web Form Life Cycle

1 案例调试中的排错处理

在一个用于教学的软件系统的设计中,要完成一个从数据库中获取信息并在页面中显示的功能。在Web页面设计中,性别数据使用了两个单选按钮控件RadioButton,其他数据都用TextBox控件显示。数据库信息的检索和显示是通过按钮的事件来处理的,页面结构如下图所示:

图1

从图中可以看出,当在学号文本框中输入学号信息,点击提交按钮后,数据库中的查询结果信息就应该正确显示出来了。但是,在实际调试运行中,查询结果中性别信息的显示令人迷茫,我用了三个学号测试数据,对应的数据库中的性别字段值分别是“男,女,男”,第一次输入关键字,提交查询,页面能够正确显示数据库中的数据信息;然后,修改查询关键字,再次提交,页面也能够正确显示查询结果;再输入第三个學号信息,提交后,单选按钮显示的是“女”被选中,除了单选按钮信息不正确外,其他信息都正确显示。换一组学号测试数据,对应的数据库中的性别字段值分别是“女,男”,结果显示,第一次提交查询,能够正确显示数据库信息,但是,第二次输入对应性别为“男”的学号信息时,查询结果显示的还是“女”单选按钮选中的状态,除了性别信息显示不正确外,其他数据库信息显示都正确。在按钮事件代码中,依据数据库的查询结果设置单选按钮的代码如下:

if (dr.GetBoolean(2) == true)

RadioButton1.Checked = true;

else

RadioButton2.Checked = true;

通过测试和分析,我们找到了问题的原因,由于忽视了页面处理流程中生命周期事件的处理顺序,导致代码设计上的漏洞。对按钮事件代码做了一点修改,测试结果能正确显示数据库查询信息了。

2 页面生命周期各个阶段的处理步骤

ASP.NET页面是Web应用程序的可编程用户接口, 当ASPX页面被客户端请求时,页面的服务器端代码被执行,执行结果被送回到浏览器端;当页面提交时,Form表单的action属性默认为本提交页面,HTTP协议是一个无状态协议,在服务器端重建页面时,如何保证提交页面的所有视图状态信息(页面对象的属性和页面控件的属性)与重建页面的视图状态信息的之间的完整性呢?其实,不论页面是首次被请求,还是页面事件被提交到服务器后重建的页面,服务器在把结果页面送到浏览器前都会把当前页面的所有视图状态封装到一个隐藏的输入域VIEWSTATE中,和HTML输出流一起发送到客户端浏览中。因此,当页面被提交到服务器时,上传到服务器的信息包括当前Form表单中用户选择或输入的数据,隐藏的输入域中页面视图状态信息以及用户交互的事件信息。这三类信息被服务器接收后,会在页面生命周期中不同阶段触发不同的服务器端生命周期事件来处理这些信息,同时也实现了在不同的页面之间传递页面视图状态信息。页面生命周期包括以下几个重要阶段:

(1)页面初始化阶段:此阶段,通过依次执行的三个事件,页面自身以及页面中的控件被首次初始化。PreIntit事件是页面生命周期的进入点,依据请求页面的类型设置页面属性的值(包括IsCallBack、IsCrossPagePostback及IsPostback),实例化页面控件;Init 事件是以一种上下文相关的方法加载页面和控件部分状态,为控件集合中的每个控件设置命名容器和一个具体的ID;IntiComplete事件是只有页面才有的事件,表明初始化阶段结束,页面及控件的视图状态变更跟踪功能已被打开。

Page_Init事件事件只是在第一次载入页面时被调用,这之后每次重新载入页面首先触发的会是Page_Load事件。

(2)视图状态恢复阶段:本阶段仅在页面回发时才执行。如果页面是回发请求,则在LoadViewState事件中恢复VIEWSTATE隐藏字段内容,_VIEWSTATE隐藏字段保存着上一个请求结束时所有控件视图状态。通过控件ID为每个控件加载视图的状态,使页面视图状态恢复到上一次提交保留在服务器上的每个控件的状态信息。

(3)处理表单数据阶段:HTTP请求中包装的所有用户数据,即用

标签定义的所有输入字段的内容,都在这时进行处理。当页面提交Form时,激发LoadPostData事件, 该方法会比较控件的旧值和新值返回一个bool类型值,标识其自上一次提交后该控件的数据是否被修改,具体说,如果LoadPostData()方法返回true,说明控件的数据被修改。则页面加载后会执行RaisePostDatachangedEvent方法更新控件里的值,既用正确的回传数据更新控件状态。

(4)页面加载阶段:页面中的控件在此时创建。 如果当前请求是回发请求,则将使用从视图状态和控件状态恢复的信息加载控件属性,使他们的状态完全反映前一个状态以及从客户端发送的任何数据的状态。页面装载时调用Page_Load()事件,再依次调用各个控件OnLoad方法。在这个阶段你可以为页面上所有的服务端控件设置属性,执行所有与页面逻辑和行为有关的初始化代码。

(5)回发的客户端事件处理阶段:ASP.NET服务器控件事件处理模型中,产生于客户端的事件,通过HTTP的post方法将客户端发生的事件发送给服务器,由服务器判断什么事件将被触发,并执行相应的代码处理该事件。

(6)页面呈现阶段:处理回发事件以后,页面准备为浏览器生成输出。在呈现之前,会针对该页和所有控件保存视图状态,当页面上的控件状态已经全部保存到持久性介质时,会触发SaveStateComple事件。在呈现阶段中,页对象会针对每个控件调用Render方法,它会提供一个文本编写器,并由它产生HTML标记给浏览器。被请求Web页经过ASP.NET处理,一个服务器网页变成一个客户端网页,一个控件可能变成一个或多个HTML标记。

(7)页面卸载:完全呈现页并已将页发送至客户端后,服务器端的Web页面会被丢弃。首先为每个控件引发Unload事件,并最终为页面引发Unload事件。Unload事件存在的目的是在释放页面对象之前执行所有最后的清除工作。

3 页面控件状态和控件事件处理分析

从前面的页面生命周期各个阶段的处理过程可以看出,当页面被提交到服务器时,上传到服务器的数据在页面重建时的处理是有严格的时间顺序的:首先,在视图状态恢复阶段处理提交的_VIEWSTATE隐藏字段保存中保存的页面视图状态信息;接着,在处理表单数据阶段处理提交的Form表单中的数据;最后,引起页面回发的用户交互事件是在回发的客户端事件处理阶段完成。下面设计了一个简单的单选按钮选择页面进行印证分析

在此页面中,我们点选第一个单选项“大学生”,然后点击提交按钮,页面数据上传到服务器,在页面重建过程中,首先恢复隐藏控件中的状态信息,接着处理表单提交的数据,用表单中的数据更新控件的状态,在页面加载时,第一个单选按钮的Checed属性为true,第三个单选按钮的Checked属性为false,最后,在执行提交按钮的事件代码时,第二个单选按钮的Checed属性被设置为true,这样,页面呈现之前,有两个单选按钮的Checed属性被设置为true, 回发页面的HTML代码也证实了这一点:

至此,上述案例中的设计错误就已经很显然了。在页面第一次查询完成后,页面上显示的是数据库中的查询信息。之后,修改查询关键字,再次提交后,当前页面显示的信息随着Form一起提交到服务器,虽然这些数据连同隐藏控件中的数据在页面重建时会被恢复,就我们的设计目的而言,实际上已经没有什么意义,因为在服务器端的事件代码中,我们用新的数据库查询结果重新设置了各个控件的显示值。由于在页面中有多个单选按钮控件,所以性别信息的显示处理比其他的控件处理稍显复杂,在服务器端的事件处理代码中,依据客户端的信息重新进行数据库查询,用新的查询信息设置单选按钮的Checked属性值,这时,如果新查询的性别信息和前一次的性别信息不一样,在服务端页面重建中会出现有两个单选按钮的Checked属性值都为true的情况:一个是页面提交时,在Form表单中的单选按钮设置的值,另一个是事件代码中依据数据库查询结果新设置的单选按钮状态。这样,在浏览器页面的源代码中,我们看到至少有两个类型为radio的input控件的checked属性值都被设置为选中状态checked,所以就出现了单选按钮显示混乱的情况了。

基于以上分析可以看出,asp.net Web应用开发中,如果在页面中有多个单选按钮,即使设置了同样的groupname属性值,在服务器端多个RadioButton的checked属性都可以设置为true,单选的效果不是在服务器端实现的,而是在客户端浏览器中由HTML中的控件实现的。因此,如果单选按钮的选择状态是通过页面回发的事件代码动态设置的,那么有两种方式可以初始化单选按钮控件。一是在事件代码中,在设置单选按钮的新值之前,现将Form中的所有单选按钮的Checked设置为false,保证事件代码中单选按钮设置的唯一性;另外一种方法是在Page_load事件中完成,由于Page_load會在控件事件之前触发,也可以将按钮初始化代码放在这里。

protected void Page_Load(object sender,EventArgs e)

{if(IsPostBack)

RadioButton1.Checked = false;

RadioButton2.Checked = false;}

4 结论

理论上,只需设置客户端提交的那个RadioButton控件的checked属性值为false就可以了,出于简化代码的考虑,将所有的RadioButton的checked属性值都设置为false。如果单选的项目较多,用单选按钮列表RadioButtonList控件替换RadioButton控件是最简单和实用的方式,但是对页面生命周期的展示和分析就没有这么直观了。

【参考文献】

[1]https://www.cnblogs.com/zze46/p/7269733.html.

[2]http://www.cnblogs.com/couhujia/archive/2010/04/23/1718405.html.

猜你喜欢

控件视图代码
创世代码
创世代码
创世代码
创世代码
视图
Y—20重型运输机多视图
SA2型76毫米车载高炮多视图
ASP.NET服务器端验证控件的使用
Spreadsheet控件在Delphi数据库系统中的编程与应用