繼續上一篇文章使用jQuery.Validate進(jìn)行客戶(hù)端驗證(高級篇-上),本文將繼續介紹jQuery.Validate的高級應用——jQuery.Validate的AJAX驗證及簡(jiǎn)單擴展。
今天主要介紹的內容有:
1、如何使用jQuery.Validate進(jìn)行AJAX驗證?
2、默認jQuery.Validate在進(jìn)行AJAX驗證時(shí)返回必須是bool類(lèi)型,如何返回一個(gè)對象包括錯誤消息及驗證結果?
3、在反復使用jQuery.Validate進(jìn)行AJAX驗證時(shí),總是需要編寫(xiě)相關(guān)AJAX參數,可否進(jìn)行進(jìn)一步封裝?
第一點(diǎn):如何使用jQuery.Validate進(jìn)行AJAX驗證?(具體見(jiàn)High-2.aspx)
jQuery.Validate為我們提供了一個(gè)方便的AJAX驗證方式(封裝了jQuery的AJAX,同時(shí)將jQuery的AJAX和jQuery.Validate的驗證很好的結合在一起),在此我僅僅介紹jQuery.Validate在A(yíng)SP.NET下如何進(jìn)行AJAX驗證,PHP、JSP等請查看官方例子。
我是采用jQuery.Validate+WebService進(jìn)行AJAX驗證,客戶(hù)端編寫(xiě)jQuery.Validate的remote驗證屬性,服務(wù)器端采用WebSerice進(jìn)行接收參數進(jìn)行驗證。
首先來(lái)看下jQuery.Validate的remote屬性如何編寫(xiě)AJAX驗證規則:
05 | <%=txtUid.UniqueID %>: |
11 | url: "WebService.asmx/CheckUid", |
13 | data: {uid:function(){ return jQuery("#<%=txtUid.ClientID %>").val();}} |
如果使用過(guò)jQuery.ajax的朋友肯定會(huì )很熟悉這段代碼,jQuery.Validate的remote采用和jQuery.ajax相同的參數設置(原因就上面所說(shuō)的封裝了jQuery.ajax的原因)。
這邊來(lái)詳細講解下jQuery.Validate的remote的一些知識:
1、jQuery.Validate的remote默認可以直接填寫(xiě)遠程驗證的地址,格式為:remote:”validate.aspx”,但是很多情況下這個(gè)遠程驗證需要提交參數、返回類(lèi)型等限制,所以就可以采用在“{}”中編寫(xiě)具體屬性的方式來(lái)包裝提交參數。
2、jQuery.Validate的remote官方代碼中,遠程的輸出只能是true或者false,不允許有其他輸出,這個(gè)我覺(jué)得不太好,具體的擴展在后面我會(huì )講到。
3、jQuery.Validate的remote在使用時(shí)如果想提交參數需要以JSON的方式提交格式如下:
3 | return jQuery("#<%=txtUid.ClientID %>").val(); |
此處肯定會(huì )有人不明白,為什么參數需要以function的形式提交,而不是直接寫(xiě)
jQuery("#<%=txtUid.ClientID %>").val();
這里我要說(shuō)明的是:jQuery.Validate的驗證規則是在頁(yè)面加載的時(shí)候就已經(jīng)被加載了的,如果還是像以往一樣直接寫(xiě)"jQuery("#<%=txtUid.ClientID %>").val();",那么驗證的時(shí)候提交給服務(wù)器端的數據永遠是頁(yè)面加載時(shí)txtUid控件的值。
而使用function的好處就是在頁(yè)面加載的時(shí)候僅僅告訴jQuery.Validate,在控件需要進(jìn)行remote驗證的時(shí)候需要調用function這個(gè)函數,這樣就保證了在執行remote驗證的時(shí)候可以獲取到最新的值
我還修改了jQuery.Validate的remote方法,先來(lái)看下我修改的代碼(具體見(jiàn)scripts/jquery.validate1.js 896行):
01 | if (previous.old !== value) { |
04 | this.startRequest(element); |
06 | data[element.name] = value; |
07 | $.ajax($.extend(true, { |
08 | //url:url,//此URL無(wú)法獲取 |
09 | url: param.url,//獲取param驗證規則中所寫(xiě)路徑 |
11 | port: "validate" + element.name, |
15 | data: param.data || data,//獲取param.data或data中所提交的參數 |
16 | success: function(response) { |
這邊我修改了url和data的獲取方式,主要是因為在真正執行的時(shí)候,變量url是空的,所以需要從param中獲取。
而data為什么要改成param.data || data,主要原因就是下面這句代碼:
data[element.name] = value;
這句代碼的意思就是:為哪個(gè)控件設置遠程驗證就獲取哪個(gè)控件的值,但是在實(shí)際的開(kāi)發(fā)中,當遇到進(jìn)行AJAX驗證的時(shí)候會(huì )出現需要同時(shí)提交多個(gè)數據的情況,此時(shí)這句代碼就是錯誤的了,所以需要改成
param.data || data,這樣就能保證在提交多個(gè)數據的時(shí)候以多個(gè)數據為準。
下面來(lái)看下webservice的代碼:
2 | public bool CheckUid(string uid) |
4 | return uid == "testuid" ? true : false; |
相當的簡(jiǎn)單,就是判斷下用戶(hù)名是不是指定的用戶(hù)名。
注意:webservice.cs中必須將[System.Web.Script.Services.ScriptService]這個(gè)特性取消注釋?zhuān)駝tAJAX驗證將無(wú)效!
第二點(diǎn):默認jQuery.Validate在進(jìn)行AJAX驗證時(shí)返回必須是bool類(lèi)型,如何返回一個(gè)對象包括錯誤消息及驗證結果?(具體見(jiàn)App_Code/WebService.cs/CheckUid)
在第一點(diǎn)中介紹jQuery.Validate知識的時(shí)候就提到了,jQuery.Validate默認直接收true或false,但是在具體的開(kāi)發(fā)中,我們會(huì )分層開(kāi)發(fā),三層或者多層,webservice在接收到驗證請求后不做具體的處理直接調用邏輯層的驗證方法,交由邏輯層進(jìn)行驗證操作(當然你也可以把驗證全部寫(xiě)在webservice中,但是這樣就體現不出分層的好處了),此時(shí)的驗證會(huì )產(chǎn)生多種情況,以最常見(jiàn)的用戶(hù)名驗證為例:
1)用戶(hù)名已存在,此時(shí)的消息應該是“用戶(hù)名已存在,請重新輸入!”
2)用戶(hù)名不符合規則,此時(shí)的消息應該是“用戶(hù)名不符合規則,請重新輸入!”
3)驗證時(shí)出現程序異常,此時(shí)的消息應該是“程序出現異常,請聯(lián)系管理員!”
可以看出,僅僅一個(gè)用戶(hù)名驗證就會(huì )出現這3種信息,如果不返回一個(gè)明確的消息,僅僅告訴用戶(hù)“用戶(hù)名有誤”,客戶(hù)端的使用者將會(huì )相當的痛苦,因為使用者并不知道他的用戶(hù)名輸入到底錯在哪了。
所以為了更好的客戶(hù)體驗,以及項目的合理性,我們在服務(wù)器端封裝一個(gè)實(shí)體類(lèi)(具體見(jiàn)AppCode/AjaxClass),代碼如下:
4 | public string Msg { get; set; } |
5 | public int Result { get; set; } |
就是一個(gè)最簡(jiǎn)單的實(shí)體類(lèi),有2個(gè)屬性,Msg和Result,Msg用于存放驗證失敗的信息,Result用于存放結果。
看下WebSerivce的代碼如何修改:
02 | public AjaxClass CheckUid(string uid) |
05 | AjaxClass ajaxClass = new AjaxClass(); |
10 | ajaxClass.Msg = "用戶(hù)名已存在,請重新輸入!"; |
13 | else if (uid.IndexOf("test") == -1) |
15 | ajaxClass.Msg = "用戶(hù)名格式不正確,用戶(hù)名必須包含test,請重新輸入!"; |
20 | ajaxClass.Msg = "格式正確!"; |
26 | ajaxClass.Msg = "程序出現異常,請聯(lián)系管理員!"; |
上面的WebService就完整的實(shí)現了我先前說(shuō)的3種錯誤情況(由于這邊僅僅是例子所以就只有表示層,實(shí)際開(kāi)發(fā)中需要分層開(kāi)發(fā),此代碼應該放入業(yè)務(wù)邏輯層)
注意:在webservice返回值前,如果檢查成功必須要為ajaxClass.Result = 1,否則客戶(hù)端驗證會(huì )無(wú)法通過(guò)。
雖然完成了服務(wù)器端的代碼修改,但是直接運行頁(yè)面還是會(huì )出錯,這是因為我上面所說(shuō)過(guò)的,jQuery.Validate的remote遠程的輸出只能是true或者false,我們來(lái)看下具體的代碼,其中注釋掉的就是原來(lái)官方的代碼:
01 | success: function(response) { |
02 | if (response.Result) {//if(response){ |
03 | var submitted = validator.formSubmitted; |
04 | validator.prepareElement(element); |
05 | validator.formSubmitted = submitted; |
06 | validator.successList.push(element); |
07 | validator.showErrors(); |
10 | //errors[element.name] = response.Result || validator.defaultMessage(element, "remote"); |
11 | errors[element.name] = response.Msg; |
12 | validator.showErrors(errors); |
14 | previous.message = response.Msg; //previous.valid = response; |
15 | previous.valid = response.Result; |
16 | validator.stopRequest(element, response.Result); |
可以看到一共修改了3處地方:
1、判斷返回值,原來(lái)是直接判斷response,現在則是判斷response.Result,因為現在的response已經(jīng)是一個(gè)包含消息及結果的對象了。
2、錯誤消息,原來(lái)的錯誤消息是直接獲取默認配置好的消息,我這邊是獲取response.Msg。
3、設置previous對象,將previous對象的消息和結果設置為AJAX返回的消息和結果,以供jQuery.Validate下面代碼的返回。
這樣jQuery.Validate的remote的方法就修改了,但是并沒(méi)有結束,原因是先前在A(yíng)JAX提交參數的時(shí)候由于jQuery.Validate的驗證規則的緣故,提交的參數并不是以JSON的格式提交的而是以{uid:function()}這樣的方式,結果就導致了無(wú)法設置jQuery.AJAX的contentType:"application/json; charset=utf-8",如果設置了會(huì )出現以下錯誤:
這樣從webservice返回的AjaxClass對象就無(wú)法像以往的JSON方式直接操作了,所以我們只能換一種格式——XML,因為webservice默認返回的數據是XML格式:
1 | <?xml version="1.0" encoding="utf-8" ?> |
3 | <Msg>用戶(hù)名格式不正確,用戶(hù)名必須包含test,請重新輸入!</Msg> |
接下來(lái)看下具體的remote方法應該如何編寫(xiě),設置dataType:”xml”,然后將XML數據轉換成一個(gè)對象以供上面我修改的jQuery.Validate的remote方法中ajaxsuccess的使用,具體看一下代碼:
05 | url: "WebService.asmx/CheckUid", |
06 | data: {uid:function(){ return jQuery("#<%=txtUid.ClientID %>").val();}}, |
07 | dataFilter: function(dataXML) { |
08 | var result = new Object(); |
09 | result.Result = jQuery(dataXML).find("Result").text(); |
10 | result.Msg = jQuery(dataXML).find("Msg").text(); |
11 | if (result.Result == "-1") { |
12 | result.Result = false; |
16 | result.Result = result.Result == "1" ? true : false; |
就是jQuery.Ajax方法dataFilter,可以在A(yíng)JAX請求成功后將數據進(jìn)行過(guò)濾處理,這里我就使用了jQuery方法把結果和消息從XML中獲取出來(lái)直接賦給一個(gè)對象,再將這個(gè)對象返回,交由ajaxsuccess使用。
這樣就算是完成了修改jQuery.Validate的remote方法,使得可以返回驗證結果及驗證消息,看下效果圖:
第三點(diǎn):在反復使用jQuery.Validate進(jìn)行AJAX驗證時(shí),總是需要編寫(xiě)相關(guān)AJAX參數,可否進(jìn)行進(jìn)一步封裝?(具體見(jiàn)High-3.aspx和jquery.validate.extension.js)
在開(kāi)發(fā)一個(gè)系統的時(shí)候經(jīng)常會(huì )用到AJAX的驗證,而如果每次都要編寫(xiě)上面那么多的代碼還是很不方便,所以我現在就來(lái)進(jìn)行一下簡(jiǎn)單的封裝,代碼如下:
02 | function GetRemoteInfo(postUrl, data) { |
09 | dataFilter: function(dataXML) { |
10 | var result = new Object(); |
11 | result.Result = jQuery(dataXML).find("Result").text(); |
12 | result.Msg = jQuery(dataXML).find("Msg").text(); |
13 | if (result.Result == "-1") { |
14 | result.Result = false; |
18 | result.Result = result.Result == "1" ? true : false; |
這個(gè)函數主要接收2個(gè)參數,一個(gè)是遠程驗證的路徑和需要提交的參數,返回包裝好的remote對象。
頁(yè)面調用也很簡(jiǎn)單,代碼如下:
01 | <script src="scripts/jquery.validate.extension.js" type="text/javascript"></script> |
02 | <script type="text/javascript"> |
03 | function InitRules() { |
04 | var dataInfo = {uid:function(){ return jQuery("#<%=txtUid.ClientID %>").val();}}; |
05 | var remoteInfo = GetRemoteInfo('WebService.asmx/CheckUid', dataInfo); |
10 | <%=txtUid.UniqueID %>: |
怎么樣?相比上面的代碼一下子干凈了很多吧?
頁(yè)面上只要做3步操作:
1、包裝好需要提交的data對象。
2、將遠程驗證地址和包裝好的data對象傳遞給封裝好的方法獲取remote對象。
3、將函數返回的remote對象放入規則中。
至此使用jQuery.Validate進(jìn)行客戶(hù)端驗證——不使用微軟驗證控件的理由這一系列就算全部寫(xiě)完了,大體上將jQuery.Validate在A(yíng)SP.NET上的一些常見(jiàn)應用講了一下,同時(shí)也提出了許多我自己修改擴展的東西,希望對正在苦惱客戶(hù)端驗證的朋友有所幫助,謝謝大家的支持了!