ASP.NET AJAX客戶端編程之旅(二)——知其所以然(轉載)

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月

作者:T2噬菌體
出處:http://leoo2sk.cnblogs.com
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章