ASP.NET提供多个验证控件进行客户端验证.每个控件都触发相应的客户端的JavaScript进行数据验证。在ASP.NET的早期版本中,客户端Javascript库是公开进行修改。从ASP.NET 2.0开始,验证控件所使用的脚本库WebUIValidation.js成为一种System.Web程序集内嵌入资源。本文着眼于了解他们的工作机制和在页面的验证过程。
验证控件的工作机制
为了演示asp.net验证过程,我们新建一个名叫SimpleValidationTest的简单web application.
1.用VS新建一个website:SimpleValidationTest
2.
- <form id="form1" runat="server">
- <div>
- <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
- <asp:RequiredFieldValidator
- ID="RequiredFieldValidator1" runat="server" ErrorMessage="RequiredFieldValidator"
- ControlToValidate="TextBox1">
- </asp:RequiredFieldValidator>
- <asp:Button ID="Button1" runat="server" Text="Button" />
- <asp:ValidationSummary ID="ValidationSummary1" runat="server" />
- </div>
- </form>
当asp.net服务器端验证控件被使用时,在页面最终输出javascript代码来实现验证.asp.net所有的验证控件都继承自BaseValidator.在该类中注册通用的javascript脚本,输出通用的html.
当页面加入了asp.net验证控件.form将发生改变:
- onsubmit="javascript:return WebForm_OnSubmit();"
在OnPreRender方法里,调用RegisterValidatorCommonScript来注册验证控件通用的javascript脚本,最终通过RegisterValidatorCommonScript函数来实现.
在render阶段,通过Page.ClientScript.RegisterOnSubmitStatement方法把onsubmit添加到form 上的.
- function WebForm_OnSubmit() {
- if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)
- return false;
-
- return true;
- }
WebForm_OnSubmit函数在form提交的时候被调用.如果页面无效,页面将无法提交.该条件由alidatorOnSubmit函数决定.
- var Page_ValidationActive = false;
- if (typeof(ValidatorOnLoad) == "function") {
- ValidatorOnLoad();
- }
-
- function ValidatorOnSubmit() {
- if (Page_ValidationActive) {
- return ValidatorCommonOnSubmit();
- }
- else {
- return true;
- }
- }
ValidatorOnLoad函数遍历validators数组,并初始化每项,设置Page_ValidationActive为true.当ValidatorOnSubmit被调用时,由于Page_ValidationActive为true,ValidatorCommonOnSubmit被调用.
- function ValidatorCommonOnSubmit() {
- Page_InvalidControlToBeFocused = null;
- var result = !Page_BlockSubmit;
- if ((typeof(window.event) != "undefined") && (window.event != null)) {
- window.event.returnValue = result;
- }
- Page_BlockSubmit = false;
- return result;
- }
缺省Page_BlockSubmit被设置为false.在页面客户端验证期间Page_BlockSubmit被设置为!Page_IsValid.
深入理解页面验证
- <script type="text/javascript">
- <!--
- var Page_ValidationSummaries = new Array(document.getElementById("ValidationSummary1"));
- var Page_Validators = new Array(document.getElementById("RequiredFieldValidator1"));
-
- </script>
上面的代码显示ValidationSummary1控件对象被加入到Page_ValidationSummaries数组,RequiredFieldValidator1控件对象被加入到Page_Validators数组中.
Validator控件主要有controltovalidate, errormessage, evaluationfunction 和 initialvalue.controltovalidate的值对应要验证的控件ID.errormessage值是错误消息提示.initialvalue为初始值.evaluationfunction由服务器端验证控件的类型决定.
Validator type |
evaluationfunction |
Required Field Validator |
RequiredFieldValidatorEvaluateIsValid |
Range Validator |
RangeValidatorEvaluateIsValid |
Custom Validator |
CustomValidatorEvaluateIsValid |
Compare Validator |
CompareValidatorEvaluateIsValid |
此前,我们提到到Page_IsValid决定页面是否有效。但是,那些函数设置该值以及这些函数如何被调用的?
使用我们上面的例子来显示这个过程. 我们监测button控件呈现HTML的过程.缺省情况下,每个按钮控件都会加上下面属性.
- onclick="javascript:WebForm_DoPostBackWithOptions(new
- WebForm_PostBackOptions("Button1", "", true, "", "", false, false))"
上面的onclick属性由按钮的AddAttributesToRender方法添加.函数WebForm_DoPostBackWithOptions和WebForm_PostBackOptions在WebForms.js中.WebForm_DoPostBackWithOptions使用WebForm_PostBackOptions对象作为参数,调用Page_ClientValidate函数.Page_ClientValidate函数负责设置Page_IsValid变量的值.
下面显示Button控件点击完整的处理过程.
1. 按钮被点击
2. 函数WebForm_DoPostBackWithOptions被调用
- function WebForm_DoPostBackWithOptions(options) {
- var validationResult = true;
- if (options.validation) {
- if (typeof(Page_ClientValidate) == 'function') {
- validationResult = Page_ClientValidate(options.validationGroup);
- }
- }
- if (validationResult) {
- if ((typeof(options.actionUrl) != "undefined") &&
- (options.actionUrl != null) &&
- (options.actionUrl.length > 0))
- {
- theForm.action = options.actionUrl;
- }
- if (options.trackFocus) {
- var lastFocus = theForm.elements["__LASTFOCUS"];
- if ((typeof(lastFocus) != "undefined") && (lastFocus != null)) {
- if (typeof(document.activeElement) == "undefined") {
- lastFocus.value = options.eventTarget;
- }
- else {
- var active = document.activeElement;
- if ((typeof(active) != "undefined") && (active != null)) {
- if ((typeof(active.id) != "undefined") &&
- (active.id != null) &&
- (active.id.length > 0))
- {
- lastFocus.value = active.id;
- }
- else if (typeof(active.name) != "undefined") {
- lastFocus.value = active.name;
- }
- }
- }
- }
- }
- }
- if (options.clientSubmit) {
- __doPostBack(options.eventTarget, options.eventArgument);
- }
- }
3. 函数Page_ClientValidate被调用
- function Page_ClientValidate(validationGroup) {
- Page_InvalidControlToBeFocused = null;
- if (typeof(Page_Validators) == "undefined") {
- return true;
- }
- var i;
- for (i = 0; i < Page_Validators.length; i++) {
- ValidatorValidate(Page_Validators[i], validationGroup, null);
- }
- ValidatorUpdateIsValid();
- ValidationSummaryOnSubmit(validationGroup);
- Page_BlockSubmit = !Page_IsValid;
- return Page_IsValid;
- }
4. Page_IsValid 被设置.
5. form 被提交
6. onSubmit 事件被触发
7. 返回WebForm_OnSubmit
8. 返回 ValidatorOnSubmit
9. 返回 ValidatorCommonOnSubmit
10. 返回 !Page_BlockSubmit
11. 返回 !(!Page_IsValid)
如果页面是有效的,将提交页面.如果页面无效,就不能提交页面,同时页面的validation summary 控件显示错误消息.函数ValidatorUpdateIsValid 和 ValidationSummaryOnSubmit负责这方面的功能.
自定义验证控件
在前面内容中,我们看到页面的验证过程内部机制。在下面的例子,我们将展示根据条件关闭或打开验证。在我们上面的示例程序中添加另一个文本框和自定义验证。验证函数决定验证的启用与否。该validateTextBox1函数接受两个参数,src和args。当在TextBox2中输入的值时,args.Value为true.RequiredFieldValidator1以编程方式被禁用。这是通过利用内置的ValidatorEnable功能来实现的.它需要这两个参数:验证器的名称和一个布尔型标志启用/禁用。自定义验证器的errormessage属性使用代码动态改变.根据用户输入,如果args.IsValid为false则页面无法提交。
- <html xmlns="http://www.w3.org/1999/xhtml" >
- <head runat="server">
- <title>Understanding .NET Validation</title>
- <script type="text/javascript">
- function validateTextBox1(src, args)
- {
- if (args.Value == "true")
- {
- ValidatorEnable(RequiredFieldValidator1, false);
- src.errormessage = "TextBox1 required field validator is disabled";
- }
- else
- {
- ValidatorEnable(RequiredFieldValidator1, true);
- src.errormessage = "Enter true, not '"+args.Value+"' to disable TextBox1 required field validator";
- }
- args.IsValid = false;
- }
- </script>
- </head>
- <body>
- <form id="form1" runat="server">
- <div>
- TextBox 1: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
- <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
- Text="*" ControlToValidate="TextBox1"
- Display="Dynamic"
- ErrorMessage="TextBox1 is required"></asp:RequiredFieldValidator>
- <br />
- Disable required field for TextBox1?
- <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
- <asp:CustomValidator ID="CustomValidator1" runat="server"
- Text="*" ControlToValidate="TextBox2" Display="Dynamic"
- ErrorMessage="CustomValidator"
- ClientValidationFunction="validateTextBox1"
- ValidateEmptyText="True"></asp:CustomValidator>
- <asp:ValidationSummary ID="ValidationSummary1" runat="server" />
- <asp:Button ID="Button1" runat="server" Text="Button" />
- </div>
- </form>
- </body>
- </html>