您的位置:首页 > 编程语言 > ASP

ASP.NET:创建Linked ValidationSummary, 深入理解ASP.NET的Validation

2007-05-12 01:52 1276 查看
<input type="submit" name="btnSignIn" value="Sign in" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("btnSignIn", "", true, "", "", false, false))" id="btnSignIn" class="button" />
通过onclick事件,我们可以看到,一个命名为WebForm_DoPostBackWithOptions的javascript function被调用,该function接收一个称为WebForm_PostBackOptions类型的对象。该类型被定一个在JavaScript1中(还记得JavaScript1指的是什么吗? 上溯到第三段)。

function WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit) {

         this.eventTarget = eventTarget;

         this.eventArgument = eventArgument;

         this.validation = validation;

         this.validationGroup = validationGroup;

         this.actionUrl = actionUrl;

         this.trackFocus = trackFocus;

         this.clientSubmit = clientSubmit;

     }


该对象具有这样的表述的是关于Postback context的一些信息,比如:


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);

         }

     }


在开始的时候,调用Page_ClientValidate进行客户端验证。我们来着重分析上面的javascript,看看具体的流程。Page_ClientValidate被定义在Javascript2中。

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;

     }


上面的代码中,首先通过Page_Validators判断Page是否存在验证控件。我们在预先定义了Page_Validators 数组(还记得我们之前介绍的两个Array——Page_ValidationSummaries和Page_Validators吗?)。虽有遍历所有的验证控件,并调用ValidatorValidate方法执行每个验证控件的客户端验证。我们进一步看看ValidatorValidate又是如何定义的(ValidatorValidate定义在Javascript2中)。

function ValidatorValidate(val, validationGroup, event) {

         val.isvalid = true;

         if ((typeof(val.enabled) == "undefined" || val.enabled != false) && IsValidationGroupMatch(val, validationGroup)) {

             if (typeof(val.evaluationfunction) == "function") {

                 val.isvalid = val.evaluationfunction(val);

                 if (!val.isvalid && Page_InvalidControlToBeFocused == null &&

                     typeof(val.focusOnError) == "string" && val.focusOnError == "t") {

                     ValidatorSetFocus(val, event);

                 }

             }

         }

         ValidatorUpdateDisplay(val);

     }


首先通过IsValidationGroupMatch判断验证控件的ValidationGroup是否和触发Postaback的Control对应的ValidationGroup相互匹配。因为只有在匹配的前提下才进行相关验证控件的验证工作。然后调用验证控件的evaluationfunction function来进行验证。通过前面的分析,我们知道RequiredFieldValidator的evaluationfunction为RequiredFieldValidatorEvaluateIsValid,而CustomValidator的evaluationfunction为CustomValidatorEvaluateIsValid。我们来看看这两个function是如何定义的。他们都定义在Javascript2中。


function RequiredFieldValidatorEvaluateIsValid(val) {

             return (ValidatorTrim(ValidatorGetValue(val.controltovalidate)) !=       ValidatorTrim(val.initialvalue))

         }

         function ValidatorGetValue(id) {

             var control;

             control = document.getElementById(id);

             if (typeof(control.value) == "string") {

                 return control.value;

             }

             return ValidatorGetValueRecursive(control);

         }

         function ValidatorGetValueRecursive(control)

         {

             if (typeof(control.value) == "string" && (control.type != "radio" || control.checked == true)) {

                 return control.value;

             }

             var i, val;

             for (i = 0; i<control.childNodes.length; i++) {

                 val = ValidatorGetValueRecursive(control.childNodes[i]);

                 if (val != "") return val;

             }

             return "";

         }

         function ValidatorTrim(s) {

             var m = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);

             return (m == null) ? "" : m[1];

         }





function CustomValidatorEvaluateIsValid(val) {

             var value = "";

             if (typeof(val.controltovalidate) == "string") {

                 value = ValidatorGetValue(val.controltovalidate);

                 if ((ValidatorTrim(value).length == 0) &&

                     ((typeof(val.validateemptytext) != "string") || (val.validateemptytext != "true"))) {

                     return true;

                 }

             }

             var args = { Value:value, IsValid:true };

             if (typeof(val.clientvalidationfunction) == "string") {

                 eval(val.clientvalidationfunction + "(val, args) ;");

             }

             return args.IsValid;

         }




在ValidatorValidate中,当我们通过调用各个验证控件的evaluationfunction来进行客户端端的验证后,对于没有通过验证的验证控件,通过调用ValidatorSetFocus设置相应控件的焦点。在这里就不在深入探讨了。接着通过调用ValidatorUpdateDisplay来根据我们制定的Display和不同浏览器,来设置错误消息的显示方式。

function ValidatorUpdateDisplay(val) {

         if (typeof(val.display) == "string") {

             if (val.display == "None") {

                 return;

             }

             if (val.display == "Dynamic") {

                 val.style.display = val.isvalid ? "none" : "inline";

                 return;

             }

         }

         if ((navigator.userAgent.indexOf("Mac") > -1) &&

             (navigator.userAgent.indexOf("MSIE") > -1)) {

             val.style.display = "inline";

         }

         val.style.visibility = val.isvalid ? "hidden" : "visible";

     }


实际上到现在为止,所有的验证工作已经完成。接下来我们来看看验证失败后相应的错误消息是如何显示的。所以我们要看看ValidatorUpdateDisplay的定义了。

分析完ValidatorValidate,我们在回到Page_ClientValidate上面。现在我们接着分析一下的执行流程。通过调用ValidatorValidate执行完各个验证控件的验证后,接着调用的是ValidatorUpdateIsValid()和ValidationSummaryOnSubmit(validationGroup)。ValidatorUpdateIsValid通过遍历每个验证控件来查看他们是否通过验证,最终确定这个页面是否通过验证。ValidationSummaryOnSubmit通过拼接字符串的形式在ValidationSummary显示对应的错误消息。这正是我们可以将错误消息写成超链接的原因所在。

function ValidatorUpdateIsValid() {

         Page_IsValid = AllValidatorsValid(Page_Validators);

     }

     function AllValidatorsValid(validators) {

         if ((typeof(validators) != "undefined") && (validators != null)) {

             var i;

             for (i = 0; i < validators.length; i++) {

                 if (!validators[i].isvalid) {

                     return false;

                 }

             }

         }

         return true;

     }

     function ValidationSummaryOnSubmit(validationGroup) {

         if (typeof(Page_ValidationSummaries) == "undefined")

             return;

         var summary, sums, s;

         for (sums = 0; sums < Page_ValidationSummaries.length; sums++) {

             summary = Page_ValidationSummaries[sums];

             summary.style.display = "none";

             if (!Page_IsValid && IsValidationGroupMatch(summary, validationGroup)) {

                 var i;

                 if (summary.showsummary != "False") {

                     summary.style.display = "";

                     if (typeof(summary.displaymode) != "string") {

                         summary.displaymode = "BulletList";

                     }

                     switch (summary.displaymode) {

                         case "List":

                             headerSep = "<br>";

                             first = "";

                             pre = "";

                             post = "<br>";

                             end = "";

                             break;

                         case "BulletList":

                         default:

                             headerSep = "";

                             first = "<ul>";

                             pre = "<li>";

                             post = "</li>";

                             end = "</ul>";

                             break;

                         case "SingleParagraph":

                             headerSep = " ";

                             first = "";

                             pre = "";

                             post = " ";

                             end = "<br>";

                             break;

                     }

                     s = "";

                     if (typeof(summary.headertext) == "string") {

                         s += summary.headertext + headerSep;

                     }

                     s += first;

                     for (i=0; i<Page_Validators.length; i++) {

                         if (!Page_Validators[i].isvalid && typeof(Page_Validators[i].errormessage) == "string") {

                             s += pre + Page_Validators[i].errormessage + post;

                         }

                     }

                     s += end;

                     summary.innerHTML = s;

                     window.scrollTo(0,0);

                 }

                 if (summary.showmessagebox == "True") {

                     s = "";

                     if (typeof(summary.headertext) == "string") {

                         s += summary.headertext + "\r\n";

                     }

                     var lastValIndex = Page_Validators.length - 1;

                     for (i=0; i<=lastValIndex; i++) {

                         if (!Page_Validators[i].isvalid && typeof(Page_Validators[i].errormessage) == "string") {

                             switch (summary.displaymode) {

                                 case "List":

                                     s += Page_Validators[i].errormessage;

                                     if (i < lastValIndex) {

                                         s += "\r\n";

                                     }

                                     break;

                                 case "BulletList":

                                 default:

                                     s += "- " + Page_Validators[i].errormessage;

                                     if (i < lastValIndex) {

                                         s += "\r\n";

                                     }

                                     break;

                                 case "SingleParagraph":

                                     s += Page_Validators[i].errormessage + " ";

                                     break;

                             }

                         }

                     }

                     alert(s);

                 }

             }

         }

     }


四、ASP.NET是如何实现服务端验证的?

前面我们花了很大的篇幅介绍了客户端验证,通过介绍我们知道了,客户端验证和错误消息的显示均由Javascript来完成。现在我们来简单看看服务端验证。客户端通过调用__doPostBack实现向服务端的Postback(具体的Postback可以参考我的文章:《浅谈ASP.NET的Postback》),并进行验证控件的服务端验证,错误消息直接通过Html显示出来。比如下面是一段CustomValidator的验证逻辑。

protected void ctmUserName_ServerValidate(object source, ServerValidateEventArgs args)

         {

             if (this.txtUserName.Text.Trim() != "adm")

             {

                 args.IsValid = false;

                 return;

             }

             args.IsValid = true;

         }


如果上面的验证没有通过,最终呈现在客户端浏览器上的将如下图所示,后面是显示验证错误消息的HTML。



 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: