网站首页/技术开发列表/内容

深入讲解 ASP+ 验证 (转自ms 二)

技术开发2022-06-28阅读
客户端 API

有一个可以在客户机上使用的小型 API,以便在您自己的客户端代码中实现各种效果。因为某些例程不可能隐藏,所以理论上讲,您可以利用客户端验证脚本所定义的所有变量、特性和函数。不过,其中许多都是可以更改的实施细节。以下总结了我们鼓励您使用的客户端对象。

表 3. 客户端对象

名称 类型 说明
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">
document.all["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) {
lblZip.ForeColor = valZip.IsValid? Color.Black : Color.Red;

}

上述方法一切都很完美,但是,只要您如上所述修改验证,就会发现除非您在客户机上进行了相同的操作,否则看起来会非常不一致。验证框架会使您避免许多这种双重效果,但是无法避免您必须在客户机和服务器上同时实现的其它效果。以下是在客户机上执行同一任务的片段:

<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="[0-9]{5}" /><br>

<script language=javascript>
function txtZipOnChange() {
 //如果客户端验证未处于活动状态,则不执行任何操作
 if (typeof(Page_Validators) == "undefined")return;
 //更改标签的颜色
 lblZip.style.color = valZip.isvalid ? "Black" : "Red";
}
</script>

Beta 1 客户端 API

对于 Beta 1 版,一些可以从客户端脚本调用的函数会造成其它一些情况。

表 4. 从客户端脚本调用的函数

名称 说明
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 = !chkSameAs.Checked;
rfvalShipAddress.Enabled = enableShip;
base.Validate();
}
}

以下是客户端等效的代码:

<input type=checkbox runat=server id=chkSameAs
 onclick="OnChangeSameAs();" >与付款地址相同<br>
<script language=javascript>
function OnChangeSameAs() {
var enableShip = !event.srcElement.status;
ValidatorEnable(rfvalShipAddress, enableShip);
}
</script>


有效性规则和有用的错误信息

每个验证器会显示有关特定控件特定情况的特定错误信息。其中有一些确认是否有效的规则,开始,您作为一个开发人员可能会有些混淆,但是如果要生成对用户有实际帮助的错误信息,这些规则是必要的。

所有空的验证器(除了 RequiredFieldValidator)均会被认为有效。如果某个空值无效,您通常需要一个 RequiredFieldValidator 和一个其它验证器。您需要这样做,因为一般情况下,您总是希望对空验证器和有效性显示不同的错误信息。您也可以使用不明确的信息,例如“您必须输入一个值,并且该值必须在 1 和 10 之间”。

在输入字段无法转换为指定数据类型时使用的另一个特殊规则与 CompareValidator 和 RangeValidator 有关。对指定了 ControlToCompare 的 CompareValidator 进行的有效性评估过程类似如下所述:

如果 ControlToValidate 引用的输入字段为空,则有效。
如果 ControlToValidate 引用的输入字段无法转换成所需数据类型,则无效。
如果 ControlToCompare 引用的输入字段无法转换成所需数据类型,则有效。
输入字段转换成所需数据类型并进行比较。
第三步看起来有些不符合直觉。之所以这样评估,是因为如果验证器同时检查多个字段的有效性,很难为该验证器写出有意义的错误信息。应使用一个独立的验证器来报告 ControlToCompare 输入字段中的错误情况。RangeValidator 的工作方式类似,具有 maximum 和 minimum 属性。


Enabled、Visible 和 Display 属性的作用

验证器的 Enabled、Visible 和 Display 属性之间的区别可能不是非常明显。

Display=None 可以用来指定验证器不直接显示任何内容,但是仍然进行评估,仍然影响总体的有效性,并且仍可以将错误放在客户机和服务器上的摘要中。对于客户端验证,这些值确定使用可见性样式特性还是使用显示样式特性来打开或关闭验证器。对于服务器端验证,Display=Dynamic 表示输入有效时不显示任何内容,而 Display=Static 表示显示一个不换行的空格 (" ")。使用最后一个设置是为了表中只包含验证器的单元格在有效时,不会折叠成不显示任何内容。

为什么不只使用 Visible=false 使验证器不可见呢?在 ASP+ 中,控件的 Visible 属性有许多含义:Visible=false 的控件根本不会被处理来预显示或显示。正是因为这种含义,验证器的 Visible=false 意味着不仅不会显示任何内容,而且无法使用。不会对这样的验证器进行评估,不会影响页面的有效性,也不会将错误放在摘要中。

Enabled 则为中性。对于大多数情况,Enabled=false 与 Visible=false 的效果完全相同。在 Beta 1 版或更高版本中,存在一个重要的区别:在客户端验证中,禁用的验证器仍会发送到浏览器中,但是处于禁用状态。您可以使用客户端脚本中的 ValidatorEnable 函数激活该验证器。

使用 Visible 或 Enabled 控制是否进行验证时,应注意上述服务器上的事件顺序。或者在验证之前进行更改,或者在更改之后重新验证。否则,它们的 IsValid 值不会将更改反映到属性上。


CustomValidator 控件

扩展验证框架最简单的方法是使用 CustomValidator 控件。该控件既可以用来执行其它验证控件无法进行的验证,也可以执行需要访问服务器上信息(例如数据库或 Web 服务)的验证。

如果添加了只定义一个服务器验证函数的 CustomValidator,您会注意到,该验证器并不参与客户端验证。当用户使用 tab 键在各字段之间切换时,CustomValidator 不会更新,并且需要往返服务器一次以执行其验证。如果要使用 CustomValidator 执行不需要任何服务器上信息的检查,您也可以使用 ClientValidationFunction 属性让验证器完全参与客户端验证。假设您提供了一个 ClientValidationFunction,理想情况下,应与服务器验证处理程序执行完全相同的检查。但实际上,只是执行该验证的一部分。客户端验证函数进行的验证不要超过在服务器上执行的验证,因为黑客很容易绕过该验证函数。

以下是在客户机和服务器上使用 CustomValidator 的一个简单示例,只检查输入是否是偶数。以下先介绍服务器函数(在 C# 中):

public bool ServerValidation(object source, string value) {
try {
int i = int.FromString(value);
return ((i % 2) == 0);
} catch {
return false;
}
}

以下是该函数在客户机上的声明方法,以及一个执行相同检查的客户端验证函数。这通常是 JScript 形式,不过如果您的目标是 Microsoft® Internet Explorer,也可以使用 VBScript® 形式。

<asp:CustomValidator id="customVal2" runat=server
ErrorMessage="数字不可以被 2 除!" 
ControlToValidate="txtCustomData"
OnServerValidationFunction=ServerValidation
ClientValidationFunction="CheckEven" /><br>
Data Field : <asp:TextBox id="txtCustomData" runat="server" />
<script language=javascript>
<!--
function CheckEven(source, value) {
var val = parseInt(value, 10);
if (isNaN(val))
return false;
return ((val % 2) == 0);
}
// -->
</script>

以下是使用 CustomValidator 的一些注意事项:

与所有其它验证控件类似(RequiredFieldValidator 除外),如果输入字段为空,则认为 CustomValidator 有效。
如果使用较旧的浏览器,或者关闭了客户端验证,将无法调用客户端验证函数。在定义该函数之前,您不必检查所用浏览器的功能,但是需要确保浏览器不会因为定义而造成脚本错误。一定要使您的客户端代码作为 HTML 注释,如下例所示。
两个参数传递到您的客户端函数中,与传递给服务器函数的参数对应。第一个是客户端验证器元素,第二个是 ControlToValidate 指定的控件值。不过,在客户机上,您可以选择不为函数定义参数,这样也会正常工作。
如果使用 Beta1 版或更高版本,您可以保留 ControlToValidate 为空。在该模式中,服务器函数每次往返总会触发一次,客户端函数每次尝试提交时总会触发一次。您可以使用该特性来验证其它方法无法验证的控件,例如 CheckBoxList 或单独的单选按钮。如果条件是基于多个控件,并且您不希望用户使用 tab 键在页面上各字段之间切换时评估该条件,可以使用该方法。
Beta 1 版或更高版本中的另一个选项是挂接多个控件的 change 事件。方法是加入一些调用客户端函数 ValidatorHookupControl 的内嵌脚本,如上所述。

哪些控件可以被验证?

要使控件可以被验证控件引用,该控件必须具有验证属性。所有可以验证的控件均具有 ValidationPropertyAttribute 属性,该属性指明验证时应读取的属性。如果编写自己的控件,可以通过提供其中一个特性来指定要使用的属性,从而使该控件参与验证。

要使验证可以在客户端正常进行,该属性必须与客户端显示的 HTML 元素的 value 特性对应。许多复杂的控件(例如 DataGrid 和 Calendar)在客户端没有值,只能在服务器上进行验证。因此,只有最接近 HTML 元素的控件才可以参与验证。此外,控件必须在客户端具有单个逻辑值。因此,RadioButtonList 可以被验证,但是 CheckBoxList 不可以。


到此为止

上述对 ASP+ 验证的讲解可能已经超过了您要了解的内容。尽情享用吧!

……

相关阅读