深入讲解 ASP+ 验证 (转自ms 一)
2024-05-04 11:06:24
供稿:网友
深入讲解 asp+ 验证
anthony moore
microsoft corporation
2000年10月
摘要:有关使用 asp+ 验证 web 控件的详细讲解。
目录
简介
入门
何时发生何事?
服务器端的验证序列
客户端的验证
有效性规则和有用的错误信息
enabled、visible 和 display 属性的作用
customvalidator 控件
哪些控件可以被验证?
到此为止
--------------------------------------------------------------------------------
简介
这篇文章详细讲解了 asp+ 验证控件的工作方式。如果要生成其中包含验证控件的复杂页面,或是要扩展验证框架,建议您阅读本文。如果要学习使用验证控件,或是要决定是否使用验证控件,请参见“asp+ 中的用户输入验证(英文)”。
入门
我们知道,在整个 asp+ 开发过程中,了解验证非常重要。看看如今的大多数商业 web 站点,您会发现,这些站点中有许多表单,这些表单明显是通过执行大量手写的代码来执行验证。编写验证代码并不是一件有趣的工作。如果要通过编写代码来显示数据表或动态生成图表,可能会很吸引人,但是没有人可以向他的同事证实这种很“酷”的方法能够禁止在姓名字段中输入空值。
因为其它一些原因,web 应用程序的验证也是非常麻烦的。html 3.2 对您可以控制的内容或可以从用户处得到的反馈的限制很多,因此无法应用在功能更全的客户机上可以使用的技巧,例如禁止用户输入某些字符,或发出嘀声。使用浏览器脚本可能会产生更强大的验证。但是这种方法很难得以证实,因为客户浏览器中并非一定有脚本,并且恶意的用户可以绕过。因此,为了保证站点安全,有必要对服务器进行同样的检查。
在开发 asp+ 时,我们的初衷是只使用一个控件来处理验证,可能本该是一个能够显示错误的 textbox 控件。可是到了设计该控件时,却发现无法实现这种愿望。我们研究了大量的数据输入表单,试图找到可以适用于尽可能多的表单的一种解决方案。我们发现,数据输入表单具有许多有趣的特性:
尽管错误信息或图标经常与输入元素相邻,但是它们几乎总是位于表的不同单元格中。
页面中经常会有一个区域来汇总所有错误。
许多站点包含客户端脚本,以便提供更快捷的反馈,同时防止白白地在与服务器之间往返。
许多包含客户端脚本的站点在出现错误时会显示信息框。
不仅会验证文本输入,还会验证下拉列表和单选按钮。
如果某个字段为空,站点通常会显示与该条目无效时不同的信息或图标。
许多有效性检查可以很好地代替常用的表达式。
验证通常是基于两个输入之间的比较结果。
90% 或 90% 以上的验证任务是一些常见的操作,例如检查姓名或邮政编码。大多数站点似乎仍在重复进行这些工作。
因为站点之间的差别通常太大,无法获得一种完美的解决方案来处理每个站点的所有验证任务。
考虑了上述所有情况,最终获得的解决方案包括五个验证器控件、validationsummary 控件以及与 page 对象的集成。同时很明显,该解决方案需要扩展,在客户机和服务器上均需要有一个 api 来配合。
我们在研究进行的各种验证时发现,我们似乎需要一个更大的工具箱。在大多数组件环境中,例如 microsoft® activex®,我们可能本来试图将所有验证控件的功能集成到一个控件中,处理不同模式下的不同属性。不过,幸好 microsoft® .net 框架中有神奇的继承性,可以提供一套控件来对特定的属性进行特定的验证,因为派生每个新控件所需的额外工作量非常小。
这些控件所完成的大多数工作均在其公用的父级 basevalidator 中实现。您也可以从 basevalidator 或其它控件派生来完成各项工作。实际上,即使 basevalidator 都懒得实现其自己的 text 属性,而是从 label 属性继承。
何时发生何事?
在处理包含验证 web 控件的页面时,了解事件序列非常有效。如果某个验证条件是可选的,您需要准确了解客户机和服务器上何时进行验证。如果要自己编写验证例程,可能会非常耗时,或者有副作用。同时,了解调用验证例程的时机也很重要。
首先,让我们看一下服务器。
服务器端的验证序列
了解页面的有效期非常重要。如果习惯于在 visual basic 或类似功能齐全的客户机工具中处理表单,则需要花一定的时间来了解。页面和页面上的所有对象并非在与用户交互时一直有效,尽管有时表面上是这样。
以下是在第一次访问某个页面时一个简化的事件序列:
基于 aspx 文件创建页面及其控件。
触发 page_load 事件。
页面和控件属性保存在一个隐藏字段中。
页面和控件转换到 html。
丢弃所有内容。
现在,当用户单击某个按钮或类似控件时,将返回服务器,然后执行一个类似的事件序列。该序列称为返回序列:
基于 aspx 文件创建页面及其控件。
从隐藏字段恢复页面和控件属性。
根据用户输入更新页面控件。
触发 page_load 事件。
触发更改通知事件。
页面和控件属性保存在一个隐藏字段中。
页面和控件转换到 html。
再次丢弃所有内容。
我们为什么不将所有对象保留在内存中呢?因为使用 asp+ 建立的 web 站点无法处理数量非常大的用户。因此,服务器的内存中只保留马上要处理的内容。
何时进行服务器端验证?在第一次获取页面信息时,根本不会进行服务器端验证。大多数最终用户都非常认真,我们允许用户自己确认在表单中填写的信息是否正确,然后我们再使用红色的文字通知用户填错的信息。
在返回事件序列中,第 3 步和第 4 步之间会进行验证。也就是说,进行验证是在来自用户的数据装回控件属性后,但在大多数代码执行之前。这意味着在编写用户事件代码时,通常可以利用已经进行的验证。一般情况下,您都会希望这样做。
在该时刻进行验证的缺点是:如果您要通过编程来修改某些影响该验证的属性,该时刻就太迟了。例如,您会发现,如果通过编写代码来启用或禁用验证控件或更改验证控件的属性,在下一次处理该页之前,不会看到任何影响。通过以下两种方法可以避免这个问题:
在进行验证之前修改属性。
在属性更改之后重新验证控件。
这两种方法均需要使用在 page 对象上有效的验证属性和方法。
页面 api
page 对象包含一些与服务器端验证有关的重要属性和方法。表 1 中总结了这些属性和方法:
表 1. page 对象的属性和方法
属性或方法 说明
isvalid 属性 这是最有用的属性。该属性可以检查整个表单是否有效。通常在更新数据库之前进行该检查。只有 validators 集中的所有对象全部有效,该属性才为真,并且不将该值存入缓存。
validators 属性 该页所有验证对象的集合。这是实现 ivalidator 界面的对象的集合。
validate 方法 在验证时调用的一种方法。在 page 对象上默认的执行方式是转至每个验证器,并要求各验证器自行评估。
validators 集合对于许多任务都非常有用。该集合是实现 ivalidator 界面的对象的集合。我之所以使用对象这个词,而不是使用控件,是因为 page 对象只关注 ivalidator 界面。既然所有的验证器通常都是用来实现 ivalidator 的一些可视化控件,那么任何人都应能够使用任意的验证对象,并将验证对象加入页面中。
ivalidator 界面包含以下属性和方法:
表 2. ivalidator 界面的属性和方法
属性或方法 说明
isvalid 属性 指出单独的验证对象进行的有效性检查是否已经通过。您可以在验证后手工更改该值。
errormessage 属性 介绍验证对象要验证的错误以及可能会向用户显示的错误。
validate 方法 对验证对象执行有效性检查,以更新其 isvalid 值。
您可以使用该界面执行一些有趣的任务。例如,要将页面重置为有效的状态,请使用以下代码(如 c# 中的示例所示):
ivalidator val;
foreach(val in validators) {
val.isvalid = true;
}
要重新执行整个验证序列,请使用以下代码:
ivalidator val;
foreach(val in validators) {
val.validate();
}
如果有 beta 1 版或更高版本,也可以只对 page 对象调用 validate 方法,这样可以完成相同的任务。要在验证前进行某些更改,可以覆盖 validate 方法。本例显示一个包含验证器的页面,其中的验证器根据复选框的值开或关:
public class conditional : page {
public htmlinputcheckbox chksameas;
public requiredfieldvalidator rfvalshipaddress;
protected override void validate() {
//只检查到货地址(如果与付款地址不同)
bool enableship = !chksameas.checked;
rfvalshipaddress.enabled = enableship;
//现在执行验证
base.validate();
}
}
客户端的验证
如果您的页面启用了客户端验证,则在往返过程中会发生完全不同的事件序列。客户端的验证使用客户端 jscript® 实现。实现该验证不需要任何二进制组件。
尽管 jscript 语言的标准化做得很好,但是用于与浏览器中的 html 文档交互的文档对象模型 (document object model, dom) 没有广泛采用的标准。因此,客户端的验证只在 internet explorer 4.0 和更高版本中进行,因为该验证的对象是 internet explorer dom。
从服务器的角度来说,客户端的验证只意味着验证控件将不同的内容发送到 html 中。除此之外,其事件序列完全相同。服务器端的检查仍然执行。尽管看起来似乎多余,但是却十分重要,因为:
某些验证控件可能不支持客户端脚本。有一个很好的例子:如果要同时使用 customvalidator 和服务器验证函数,但是没有客户机验证函数。
安全性注意事项。某些人可以很容易得到一个包含脚本的页面,然后禁用或更改该页面。您不应利用脚本来阻止坏数据进入您的系统,而只应是为了用户得到更快的反馈。因此,如果要使用 customvalidator,则不应提供没有相应服务器验证函数的客户机验证函数。
每个验证控件都可以确保将一个标准的客户端脚本块发送到页面中。实际上,这只是一小部分代码,其中包含对脚本库 webuivalidation.js 中的代码的引用。这个脚本库文件包含客户端验证的所有逻辑,该文件需单独下载,并且可以存储在浏览器的缓存中。
关于脚本库
因为验证 web 控件脚本在脚本库中,所以不必将所有客户端验证的代码直接发送到页面中,尽管表面上似乎是这样做的。主要的脚本文件引用类似如下所示:
<script language="javascript"
src="/_aspx/1.0.9999/script/webuivalidation.js"></script>
默认情况下,脚本文件将安装在 "_aspx" 目录中默认的根目录下,并使用相对于根的脚本 include 指令调用,该指令以正斜线开头。该引用表明每个单独的对象不必包含脚本库,同一台计算机上的所有页面可以引用同一个文件。您会注意到,该路径中还有一个公用的语言运行时版本号,以便不同的运行时版本可以在同一台计算机上运行。
如果查看一下您默认的虚拟根目录,您会找到该文件并查看其中的内容。这些文件的位置在 config.web 文件中指定。config.web 文件是一个用于大多数 asp+ 设置的 xml 文件。以下是该文件中位置的定义:
<webcontrols
clientscriptslocation="/_aspx/{0}/script/"
/>
鼓励您阅读该脚本,以便深入了解发生的事件。不过,建议您不要修改这些脚本,因为它们的功能与特定的运行时版本紧密相连。在运行时版本更新时,这些脚本可能也需要相应的更新,您将或者放弃更改,或者面临脚本不工作的问题。如果特定项目必须更改这些脚本,先备份这些脚本,然后将您的项目指向备份文件,方法是使用私有的 config.web 文件替代这些文件的位置。如果字符串中包含格式指令 "{0}",运行时版本号将替换该指令。最好将该位置更改为一个相对引用或绝对引用。
禁用客户端的验证
有时您可能不希望进行客户端验证。如果输入字段的数目很少,客户端验证可能用处不大。您毕竟每次都要有一个需要往返服务器一次的逻辑。您会发现客户机上动态出现的信息对您的布局会有负面影响。
要禁用客户端验证,应使用 page 指令 "clienttarget=downlevel"。该指令类似以下 aspx 文件的开头:
<%@ page language="c#" clienttarget=downlevel %>
该指令的默认值为 "auto",表示您只对 microsoft internet explorer 4.0 或更高版本进行客户端验证。
注意: 不幸的是,在 beta 1 中,该指令并非仅仅是禁用验证,同时还会使所有 web 控件使用 html 3.2 标记来处理,这可能会产生意想不到的结果。最终版本提供了更好的方法来控制这个问题。
客户端事件序列
该序列是在运行包含客户端验证的页面时发生的事件序列:
在页面载入浏览器时,需要对每个验证控件进行一些初始化。这些控件作为 <span> 标记发送,其 html 特性与服务器上的特性最接近。最重要的是,此时会将验证器引用的所有输入元素“挂接”。被引用的输入元素将修改其客户端事件,以便在每次输入更改时调用验证例程。
脚本库中的代码将在用户使用 tab 键在各字段之间切换时执行。某个独立的字段更改时,将重新评估验证条件,根据需要使验证器可见或不可见。
当用户尝试提交表单时,将重新评估所有验证器。如果这些验证器全部有效,表单将提交给服务器。如果存在一处或多处错误,则会出现下述情况:
提交被取消。表单并不提交给服务器。
所有无效的验证器均可见。
如果某个验证摘要包含 showsummary=true,则将收集来自验证控件的所有错误,并使用这些错误更新其内容。
如果某个验证摘要包含 showmessagebox=true,则将收集错误,并在客户机的信息框中显示这些错误。
因为在每次输入更改时或提交时会执行客户端验证控件,所以在客户机上通常会评估这些验证控件两次或两次以上。请注意,提交后,仍将会在服务器上对这些验证控件进行重新评估。