ASP.NET AJAX客户端编程之旅(二)——知其所以然
摘要
????? 在上一篇文章中,做了一個“Hello!ASP.NET AJAX”的小例子,但是并沒有對其中的技術做解釋。這一篇中,將探討一下使用ASP.NET AJAX框架在客戶端調用后臺代碼的基本方法,并且討論異常處理的方法。
?
如何在客戶端直接調用WebService中的方法?
????? 1.Web.config中需要配置好運行ASP.NET AJAX框架相應的配置項,當然,建立一個ASP.NET AJAX Enabled Web Site項目時,Web.config已經配置好了。
????? 2.想讓某個WebService可以被JS調用,需要做一下幾步:
??????????? I.在這個WebService文件里用“using System.Web.Script.Services;”引入這個命名空間。
????????????II.在這個類的上面添加“[ScriptService]”屬性。
????????????III.在需要被調用的方法上添加“[WebMethod]”屬性。
??????????? 具體例子可以參考《ASP.NET AJAX客戶端編程之旅(一)——Hello!ASP.NET AJAX》中的SayHelloService.cs的代碼。
????? 3.調用WebService的客戶端頁面也要做相應準備。首先就是頁面中要有一個ScriptManager控件,然后需要在其中指明WebService文件的位置。如:
????????????<Services>
????????????????? <asp:ServiceReference Path="~/SayHelloService.asmx" />
????????????</Services>
?????????? ?將這段代碼放在<asp:ScriptManager>和<asp:ScriptManager />標簽之間,就可以使得這個頁面中的JS可以直接調用SayHelloService.asmx中的方法。具體代碼可以參考《ASP.NET AJAX客戶端編程之旅(一)——Hello!ASP.NET AJAX》中第二個例子中的Default.aspx的代碼。
?
????? 做好以上三項準備,這個頁面中的JS代碼就可以使用我們熟悉的“類名.方法名”的方法直接調用WebService中的方法了。
?
魔法背后的故事
????? 我們知道,雖然我們一直說是“直接調用”,但這是指在語法層面上“直接調用”。而實際上,JavaScript代碼是不可能真正直接調用后臺程序的,這中間一定使用了XMLHttpRequest對象。那么,到底是誰給我們實施了“障眼法”?答案就在下面這張圖上:
?
?
?
?
????? 上圖就是這個所謂“直接調用”真正的秘密。如圖,現在假設有個WebService類,名為Class1,有兩個方法:Method1和Method2。當這個WebService被我們用上面提到的方法處理過后,ASP.NET AJAX框架就會自動分析這個類,并且在客戶端生成一個這個類的客戶端代理(Proxy),這個代理類是一個JavaScript對象,其類名、方法名都和后臺類一致。而當我們從客戶端的JS腳本調用時,實際上調用的是這個代理類,而代理類則使用XMLHttpRequest對象,通過傳統的Ajax方式,調用后臺類。這樣,我們就感覺好像在前臺直接調用后臺類似的。
?
可是……哪里似乎還是不一樣……
????? 通過上面的分析,我們知道,ASP.NET AJAX調用后臺方法,說到底還是使用的XMLHttpRequest對象,這樣傳統Ajax的限制,就使得我們不可能真的像在后臺調用方法一樣方便。
????? 例如,我們在后臺都是用“變量=類名.方法名”或者“變量=對象名.方法名”的方式調用,這樣變量就直接獲取了這個方法的返回值,但是Ajax不行,它必須通過回調函數獲取返回值,這一點也體現在了ASP.NET AJAX的使用方法上。看上一篇文章的例子就知道,即使使用了ASP.NET AJAX框架,仍然還是需要用回調函數的,只不過是語法上簡化了。
????? 下面,正式給出調用后臺類的語法:
????? 類名.方法名(參數1,參數2,……,參數n,回調函數)
????? 也就是說,調用上有兩個差別:一是不需要使用變量接收返回值,二是要在所有參數后面加一個參數:回調函數。例如,有個類的方法,在后臺調用是:
????? var1 = Class1.Method1(Para1,Para2);
????? 換到前臺JS調用時,就是如下的樣子:
????? Class1.Method1(Para1,Para2,CallBackFunction);
????? 那么,返回值到哪里去取呢?答案是到回調函數中,回調函數的原型是:回調函數名(返回值)。當然,存儲返回值變量的名字是開發人員隨意取的,然后就可以在回調函數中使用這個返回值變量了。例如,接著上面程序,寫一個函數:
????? function CallBackFunction(result){}
????? 則在這個函數中,result就含有Class1.Method1(Para1,Para2,CallBackFunction);的返回值。
?
為什么不直接調用類中的方法,而非要經過WebService呢?
????? 上文我曾經說過,ASP.NET AJAX允許我們直接調用后臺類中的方法,但是我們不提倡這樣做,而是提倡經過WebService的過渡。其原因有如下幾點:
????? 1.要使得某個類可以被JS調用,也需要在其中做一些修改,如增加一些屬性(Attribute)等,這會對這些類造成一種“污染”。
????? 2.我們知道了,使用ASP.NET AJAX框架也需要從回調函數中獲取返回值,而不是直接獲取。考慮以下情況:如果某段JS需要調用三個后臺方法完成一個操作,那么,就需要寫三個回調函數。即要經過“調用第一個方法-第一個回調函數中調用第二個方法-第二個回調函數中調用第三個方法-第三個回調函數中取得返回值”。
這個過程很麻煩。而使用WebService后,我們可以將這個三個方法封裝到一個WebService方法里,因為WebService是支持“變量=類名.方法名”這種傳統的調用方法的。這樣經過WebService過渡,JS中只要一個回調函數就可以了。
????? 3.從本身特性上看,WebService比普通類更適合作為Ajax的后臺方法。
?
處理異常
????? 一般來說,有成功就有失敗,異步調用也是一樣,會出現請求異常的情況。在傳統的Ajax中,不論請求成功還是失敗,回調函數都會被調用,然后我們可以判斷 XMLHttpRequest對象的狀態確定請求是否成功,如果失敗了,可以進行異常處理。
????? 但是,在ASP.NET AJAX應用中,只有成功時回調函數才會被調用,那么失敗時怎么辦?其實,ASP.NET AJAX允許我們在調用后臺方法時指定兩個回調函數,語法如下:
????? 類名.方法名(參數1,參數2,……,參數n,請求成功時的回調函數,請求失敗時的回調函數)
????? 只不過在前面的應用中,我們省略了第二個回調函數。為了理解這個地方,我們做一個小實驗,打開上一篇中的ASPNETAJAXTest這個程序,將ajax.js這個文件里的內容做如下修改:
ajax.js:
?1//單擊btnSayHello時調用的JS函數?2function?btnSayHello_onClick()
?3{
?4????SayHelloService.SayHello(OnSucceeded,OnFailded);
?5}
?6
?7//成功時的回調函數
?8function?OnSucceeded(reusltText)
?9{
10????$get("result").innerHTML=reusltText;
11}
12
13//失敗時的回掉函數
14function?OnFailded(error)
15{
16????$get("result").innerHTML="調用失敗。錯誤信息:"+error.get_message();
17}
?
????? 其中異常時的回調函數有一個參數error,它是一個ASP.NET AJAX框架定義的一個對象,包含了異常信息。其中get_message()方法將返回異常信息字符串。
????? 為了看效果,我們還要到WebService里搞一點破壞,讓請求出現異常,“破壞”后的WebService如下:
SayHelloService.cs:
using?System;using?System.Web;
using?System.Collections;
using?System.Web.Services;
using?System.Web.Services.Protocols;
using?System.Web.Script.Services;
[WebService(Namespace?=?"http://tempuri.org/")]
[WebServiceBinding(ConformsTo?=?WsiProfiles.BasicProfile1_1)]
[ScriptService]
public?class?SayHelloService?:?System.Web.Services.WebService
{
????public?SayHelloService()?{?}
????[WebMethod]
????public?string?SayHello()
????{
????????//Hello?myHello?=?new?Hello();
????????//return?myHello.SayHello();
????????throw?new?Exception("我來搞破壞!");
????}
}
?
????? 這里我們手工拋出了一個異常。下面運行程序,會得到如下結果:
?
?
?
?
????? 如上圖,當出現異常時,不僅自動調用了異常處理回調函數,還很方便地取得了錯誤信息。
?
結束語
????? 本篇介紹了從JavaScript中調用WebService的一般方法、基本原理及使用異常處理,并且回答了上一篇留下的幾個問題。然而還有一個問題沒有討論:到目前為止,我們調用的后臺方法都是沒有參數的,那么如果有參數,ASP.NET AJAX可以實現JavaScript變量類型和C#變量類型的自動轉換嗎?如果是復雜類型呢?如實體類、各種對象。再進一步,如果可以,應該怎么來做呢?我們將在下一篇討論這個問題。
?
主要參考文獻
??????[1] 陳黎夫,ASP.NET AJAX程序設計-第II卷:客戶端,人民郵電出版社,2007年10月
轉載于:https://www.cnblogs.com/leoo2sk/archive/2008/07/23/1249367.html
總結
以上是生活随笔為你收集整理的ASP.NET AJAX客户端编程之旅(二)——知其所以然的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奥运年08/07/19我正式加入博客园,
- 下一篇: 只需一行代码实现增删查改,微软已经让我们