客户端的验证
如果您的页面启用了客户端验证则在往返过程中会发生完全不同的事件序列客户端的验证使用客户端 JScript® 实现实现该验证不需要任何二进制组件
尽管 JScript 语言的标准化做得很好但是用于与浏览器中的 HTML 文档交互的文档对象模型 (Document Object Model DOM) 没有广泛采用的标准因此客户端的验证只在 Internet Explorer 和更高版本中进行因为该验证的对象是 Internet Explorer DOM
从服务器的角度来说客户端的验证只意味着验证控件将不同的内容发送到 HTML 中除此之外其事件序列完全相同服务器端的检查仍然执行尽管看起来似乎多余但是却十分重要因为
某些验证控件可能不支持客户端脚本有一个很好的例子如果要同时使用 CustomValidator 和服务器验证函数但是没有客户机验证函数
安全性注意事项某些人可以很容易得到一个包含脚本的页面然后禁用或更改该页面您不应利用脚本来阻止坏数据进入您的系统而只应是为了用户得到更快的反馈因此如果要使用 CustomValidator则不应提供没有相应服务器验证函数的客户机验证函数
每个验证控件都可以确保将一个标准的客户端脚本块发送到页面中实际上这只是一小部分代码其中包含对脚本库 WebUIValidationjs 中的代码的引用这个脚本库文件包含客户端验证的所有逻辑该文件需单独下载并且可以存储在浏览器的缓存中
关于脚本库
因为验证 Web 控件脚本在脚本库中所以不必将所有客户端验证的代码直接发送到页面中尽管表面上似乎是这样做的主要的脚本文件引用类似如下所示
<script language=javascript
src=/_aspx//script/WebUIValidationjs></script>
默认情况下脚本文件将安装在 _aspx 目录中默认的根目录下并使用相对于根的脚本 include 指令调用该指令以正斜线开头该引用表明每个单独的对象不必包含脚本库同一台计算机上的所有页面可以引用同一个文件您会注意到该路径中还有一个公用的语言运行时版本号以便不同的运行时版本可以在同一台计算机上运行
如果查看一下您默认的虚拟根目录您会找到该文件并查看其中的内容这些文件的位置在 configweb 文件中指定configweb 文件是一个用于大多数 ASP+ 设置的 XML 文件以下是该文件中位置的定义
<webcontrols
clientscriptslocation=/_aspx/{}/script/
/>
鼓励您阅读该脚本以便深入了解发生的事件不过建议您不要修改这些脚本因为它们的功能与特定的运行时版本紧密相连在运行时版本更新时这些脚本可能也需要相应的更新您将或者放弃更改或者面临脚本不工作的问题如果特定项目必须更改这些脚本先备份这些脚本然后将您的项目指向备份文件方法是使用私有的 configweb 文件替代这些文件的位置如果字符串中包含格式指令 {}运行时版本号将替换该指令最好将该位置更改为一个相对引用或绝对引用
禁用客户端的验证
有时您可能不希望进行客户端验证如果输入字段的数目很少客户端验证可能用处不大您毕竟每次都要有一个需要往返服务器一次的逻辑您会发现客户机上动态出现的信息对您的布局会有负面影响
要禁用客户端验证应使用 Page 指令 clienttarget=downlevel该指令类似以下 ASPX 文件的开头
<%@ Page Language=c# clienttarget=downlevel %>
该指令的默认值为 auto表示您只对 Microsoft Internet Explorer 或更高版本进行客户端验证
注意 不幸的是在 Beta 中该指令并非仅仅是禁用验证同时还会使所有 Web 控件使用 HTML 标记来处理这可能会产生意想不到的结果最终版本提供了更好的方法来控制这个问题
客户端事件序列
该序列是在运行包含客户端验证的页面时发生的事件序列
在页面载入浏览器时需要对每个验证控件进行一些初始化这些控件作为 <span> 标记发送其 HTML 特性与服务器上的特性最接近最重要的是此时会将验证器引用的所有输入元素挂接被引用的输入元素将修改其客户端事件以便在每次输入更改时调用验证例程
脚本库中的代码将在用户使用 tab 键在各字段之间切换时执行某个独立的字段更改时将重新评估验证条件根据需要使验证器可见或不可见
当用户尝试提交表单时将重新评估所有验证器如果这些验证器全部有效表单将提交给服务器如果存在一处或多处错误则会出现下述情况
提交被取消表单并不提交给服务器
所有无效的验证器均可见
如果某个验证摘要包含 ShowSummary=true则将收集来自验证控件的所有错误并使用这些错误更新其内容
如果某个验证摘要包含 ShowMessageBox=true则将收集错误并在客户机的信息框中显示这些错误
因为在每次输入更改时或提交时会执行客户端验证控件所以在客户机上通常会评估这些验证控件两次或两次以上请注意提交后仍将会在服务器上对这些验证控件进行重新评估
客户端 API
有一个可以在客户机上使用的小型 API以便在您自己的客户端代码中实现各种效果因为某些例程不可能隐藏所以理论上讲您可以利用客户端验证脚本所定义的所有变量特性和函数不过其中许多都是可以更改的实施细节以下总结了我们鼓励您使用的客户端对象
表 客户端对象
名称 类型 说明
Page_IsValid Boolean 变量 指出页面当前是否有效验证脚本总是保持该变量为最新
Page_Validators 元素数组 这是包含页面上所有验证器的数组
Page_ValidationActive Boolean 变量 指出是否应进行验证将此变量设置为 False 可以通过编程关闭验证
isvalid Boolean 属性 每个客户端验证器均具有该属性指出验证器当前是否有效请注意在 PDC 版本中该属性混用大小写 (IsValid)
绕过客户端验证
您经常需要执行的一项任务是在页面上添加取消按钮或导航按钮在这种情况下即使页面上有错误您可能也希望使用该按钮提交页面因为客户端按钮 onclick 事件在表单的 onsubmit 事件之前发生因此可能会避免提交检查并绕过验证以下说明如何使用 HTML Image 控件作为取消按钮完成该任务
<input type=image runat=server
value=取消
onclick=Page_ValidationActive=false;
OnServerClick=cmdCancel_Click >
使用 Button 或 ImageButton 控件执行该任务会出现一些混淆因为 onclick 事件假定为同名的服务器端事件您应在客户端脚本中设置该事件
<asp:ImageButton runat=server id=cmdImgCancel
AlternateText=取消
OnClick=cmdCancel_Click/>
<script language=javascript>
documentall[cmdImgCancel ]onclick =
new Function(Page_ValidationActive=false;);
</script>
解决该问题的另一种方法是对取消按钮进行一定的设置使其在返回时不会触发客户端脚本中的提交事件HtmlInputButton 和 LinkButton 控件就是这样的例子
特殊效果
另一种常见的要求是在出错时除了由验证器自身显示的错误信息外还需要其它一些效果在这种情况下您所作的任何修改均需在服务器或客户机上同时进行假设您需要加入一个 Label根据输入是否有效来更改颜色以下是如何在服务器上实现该任务
public class ChangeColorPage : Page {
public Label lblZip;
public RegularExpressionValidator valZip;
protected override void OnLoad(EventArgs e) {
lblZipForeColor = valZipIsValid? ColorBlack : ColorRed;
}
}
上述方法一切都很完美但是只要您如上所述修改验证就会发现除非您在客户机上进行了相同的操作否则看起来会非常不一致验证框架会使您避免许多这种双重效果但是无法避免您必须在客户机和服务器上同时实现的其它效果以下是在客户机上执行同一任务的片段
<asp:Label id=lblZip runat=server
Text=Zip Code:/>
<asp:TextBox id=txtZip runat=server
OnChange=txtZipOnChange(); /></asp:TextBox><br>
<asp:RegularExpressionValidator id=valZip runat=server
ControlToValidate=txtZip
ErrorMessage=无效的邮政编码
ValidationExpression=[]{} /><br>
<script language=javascript>
function txtZipOnChange() {
//如果客户端验证未处于活动状态则不执行任何操作
if (typeof(Page_Validators) == undefined)return;
//更改标签的颜色
lor = valZipisvalid ? Black : Red;
}
</script>
Beta 客户端 API
对于 Beta 版一些可以从客户端脚本调用的函数会造成其它一些情况
表 从客户端脚本调用的函数
名称 说明
ValidatorValidate(val) 将某个客户端验证器作为输入使验证器检查其输入并更新其显示
ValidatorEnable(val enable) 获取一个客户端验证器和一个 Boolean 值启用或禁用客户端验证器如果禁用将不会评估客户端验证器客户端验证器将总是显示为有效
ValidatorHookupControl(control val) 获取一个输入 HTML 元素和一个客户端验证器修改或创建该元素的 change 事件以便在更改时更新验证器该函数适合于基于多个输入值的自定义验证器
其特殊用途是启用或禁用验证器如果您希望验证只是在特定的情况下生效可能需要在服务器和客户机上同时更改激活状态否则您会发现用户无法提交该页面
以下是上面的示例加上一个字段该字段只在取消选中某个复选框时才会进行验证
public class Conditional : Page {
public HtmlInputCheckBox chkSameAs;
public RequiredFieldValidator rfvalShipAddress;
protected override void Validate() {
bool enableShip = !chkSameAsChecked;
rfvalShipAddressEnabled = enableShip;
baseValidate();
}
}
以下是客户端等效的代码
<input type=checkbox runat=server id=chkSameAs
onclick=OnChangeSameAs(); >与付款地址相同<br>
<script language=javascript>
function OnChangeSameAs() {
var enableShip = !eventsrcElementstatus;
ValidatorEnable(rfvalShipAddress enableShip);
}
</script>