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指的是什么吗? 上溯到第三段)。
该对象具有这样的表述的是关于Postback context的一些信息,比如:
在开始的时候,调用Page_ClientValidate进行客户端验证。我们来着重分析上面的javascript,看看具体的流程。Page_ClientValidate被定义在Javascript2中。
上面的代码中,首先通过Page_Validators判断Page是否存在验证控件。我们在预先定义了Page_Validators 数组(还记得我们之前介绍的两个Array——Page_ValidationSummaries和Page_Validators吗?)。虽有遍历所有的验证控件,并调用ValidatorValidate方法执行每个验证控件的客户端验证。我们进一步看看ValidatorValidate又是如何定义的(ValidatorValidate定义在Javascript2中)。
首先通过IsValidationGroupMatch判断验证控件的ValidationGroup是否和触发Postaback的Control对应的ValidationGroup相互匹配。因为只有在匹配的前提下才进行相关验证控件的验证工作。然后调用验证控件的evaluationfunction function来进行验证。通过前面的分析,我们知道RequiredFieldValidator的evaluationfunction为RequiredFieldValidatorEvaluateIsValid,而CustomValidator的evaluationfunction为CustomValidatorEvaluateIsValid。我们来看看这两个function是如何定义的。他们都定义在Javascript2中。
在ValidatorValidate中,当我们通过调用各个验证控件的evaluationfunction来进行客户端端的验证后,对于没有通过验证的验证控件,通过调用ValidatorSetFocus设置相应控件的焦点。在这里就不在深入探讨了。接着通过调用ValidatorUpdateDisplay来根据我们制定的Display和不同浏览器,来设置错误消息的显示方式。
实际上到现在为止,所有的验证工作已经完成。接下来我们来看看验证失败后相应的错误消息是如何显示的。所以我们要看看ValidatorUpdateDisplay的定义了。
分析完ValidatorValidate,我们在回到Page_ClientValidate上面。现在我们接着分析一下的执行流程。通过调用ValidatorValidate执行完各个验证控件的验证后,接着调用的是ValidatorUpdateIsValid()和ValidationSummaryOnSubmit(validationGroup)。ValidatorUpdateIsValid通过遍历每个验证控件来查看他们是否通过验证,最终确定这个页面是否通过验证。ValidationSummaryOnSubmit通过拼接字符串的形式在ValidationSummary显示对应的错误消息。这正是我们可以将错误消息写成超链接的原因所在。
四、ASP.NET是如何实现服务端验证的?
前面我们花了很大的篇幅介绍了客户端验证,通过介绍我们知道了,客户端验证和错误消息的显示均由Javascript来完成。现在我们来简单看看服务端验证。客户端通过调用__doPostBack实现向服务端的Postback(具体的Postback可以参考我的文章:《浅谈ASP.NET的Postback》),并进行验证控件的服务端验证,错误消息直接通过Html显示出来。比如下面是一段CustomValidator的验证逻辑。
如果上面的验证没有通过,最终呈现在客户端浏览器上的将如下图所示,后面是显示验证错误消息的HTML。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201505/70d0fedaa83fd0ab31a26d15377e8b4d.jpg)
通过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。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201505/70d0fedaa83fd0ab31a26d15377e8b4d.jpg)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201505/bd5d3b71cde6ffe5b59ef6ce262b4597.jpg)
相关文章推荐
- [转贴]ASP.NET:创建Linked ValidationSummary, 深入理解ASP.NET的Validation
- ASP.NET:创建Linked ValidationSummary, 深入理解ASP.NET的Validation。(转载)
- 创建Linked ValidationSummary, 深入理解ASP.NET的Validation
- [原创]ASP.NET:创建Linked ValidationSummary, 深入理解ASP.NET的Validation
- ASP.NET:创建Linked ValidationSummary, 深入理解ASP.NET的Validation
- asp.net创建Linked ValidationSummary, 深入理解ASP.NET的Validation
- 深入理解ASP.NET的Postback
- 深入理解 ASP.NET 与客户端缓存 (Part 2 - ASP.NET 支持)
- 深入理解ASP.NET的内部运行机制
- 深入理解ASP.NET的内部运行机制
- 捕获asp.net ValidationSummary 控件消息。
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
- 深入理解 ASP.NET 动态控件 (Part 2 - 编译过程)
- 深入理解 ASP.NET 动态控件
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
- 深入理解Asp.Net中WebForm的生命周期
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
- 深入理解 ASP.NET 动态控件 (Part 3 - 页面生命周期)
- 深入理解asp.net里的IHttpHandler
- How to use ValidationSummary control in asp.net