學習WebService(一)

7.1  Web Service基本概念

Web Service主要是爲了使原來各孤立的站點之間能夠相互通信、共享資源而提出的一種接口。 Web Service所使用的是Internet上統一、開放的標準,如HTTP、XML、SOAP、WSDL等,所以Web Service可以在任何支持這些標準的環境(Windows、Linux)中使用。其中,SOAP協議(Simple Object Access Protocal,簡單對象訪問協議)是一個用於分散和在分佈式環境下交換網絡信息的基於XML的通信協議。在此協議下,軟件組件或應用程序能夠通過標準的HTTP協議進行通信。它的設計目標就是簡單性和擴展性,這有助於大量異構程序和平臺之間的互操作性,從而使存在的應用程序能夠被廣泛的用戶訪問。Web Service是構造分佈式、模塊化應用程序的最新技術發展趨勢。

因此,我們可以這樣定義Web Service:通過SOAP在Web上提供的軟件服務,使用WSDL文件進行說明,並通過 UDDI 進行註冊。Web Service 體系結構的主要優點之一是,它允許在不同平臺上以不同語言編寫的各種程序以基於標準的方式相互通信。相對以前的方案而言,Web Service 的另一大優點是使用標準的Web協議——XML、HTTP和TCP/IP,相對易用和通用。

微軟在其.NET戰略中,對其主推的Web服務做了大肆的宣揚。現在,Web服務正如火如荼地發展着,相關的各項新技術層出不窮。Web服務的發展正構築着互聯網時代美好的明天。在本節中,將向大家介紹Web服務的一些基本知識,以及如何用ASP.NET來創建Web服務和調用Web服務。

7.2  Web Service的應用場景

以前,分佈式的應用程序邏輯需要使用分佈式的對象模型,通過使用DCOM、CORBA、RMI之類的基本結構,開發人員仍可擁有使用本地模型所提供的豐富資源和精確性,並可將服務置於遠程系統中。

當已經有中意的中間件平臺(RMI、Jini、CORBA、DCOM等)時,我們爲什麼還要爲Web而煩惱呢?中間件確實提供了強大的服務實現手段,但是,這些系統有一個共同的缺陷,那就是它們無法擴展到互聯網上:它們要求服務的客戶端與系統提供的服務本身之間必須進行緊密耦合,即要求一個同類基本結構。然而這樣的系統往往十分脆弱:如果一端的執行機制發生變化,那麼另一端便會崩潰。例如,如果服務器應用程序的接口更改,那麼客戶端便會崩潰。爲了能擴展到互聯網運用,我們需要一種鬆散耦合的基本結構來解決這個問題。在些情況下就迎來了Web服務的誕生。Web Service技術是一種基於標準的Web協議的可編程組件,我們可以把Web Service看做Web上的組件,Web服務提供者開放一系列的API,開發人員通過調用這些API來集成Web服務,構建自己的應用程序。

1.SOAP

SOAP(Simple Object Access Protocal)是在分散或在分佈式環境中交換信息的簡單協議,它基於XML協議,以XML形式提供了一個簡單且輕量的用於在分散或分佈環境下交換結構化和類型信息的機制,其本身並沒有定義任何應用程序語義,如編程模型或特定語義的實現,而是通過提供一個有標準組件的包模型和在模塊中編碼數據的機制定義了一個簡單的表示應用程序語義的機制,使其能夠用於從信息傳遞到RPC的各種系統。SOAP規範定義了SOAP消息的格式,以及怎樣通過HTTP協議來使用SOAP。SOAP最引人注目的特徵是它可以在許多不同的軟件和硬件平臺上實現。這意味着 SOAP 可用於連接企業內部和外部的不同系統。過去曾試過多種方法以提出一個可用於系統集成的通用通信協議,但它們都沒有像SOAP一樣獲得廣泛的認可。爲什麼呢?因爲與許多早期的協議相比,SOAP更小巧,而且更簡單和易於實現。HTTP的普及和SOAP的簡單性使你幾乎可以在任何環境下調用它們,因此成爲XML Web Service的理想基礎。

2.WSDL

你會怎樣向別人介紹你的Web Service有什麼功能,以及每個函數調用時的參數呢?你可能會自己寫一套文檔,甚至口頭告訴需要使用你的Web Service的人。這些非正式的方法至少都有一個嚴重的問題:當程序員坐到電腦前,想要使用你的Web Service的時候,他們的工具(如Visual Studio)無法給他們提供任何幫助,因爲這些工具根本就不瞭解你的Web Service。解決方法是使用機器能閱讀的方式提供一個正式的描述文檔。Web Service描述語言(WSDL)就是這樣一個基於XML的語言,用於描述Web Service及其函數、參數和返回值。因爲是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的,這將是一個很大的好處。一些最新的開發工具既能根據你的Web Service生成WSDL文檔,又能導入WSDL文檔,生成調用相應Web Service的代碼。

3.UDDI

UDDI(通用發現、說明和集成)是Web服務的黃頁。是一套基於Web的、分佈式地爲Web Service 提供信息註冊中心的實現標準,同時包含一組能使企業將自身提供的Web Service註冊使得別的企業能夠發現的訪問協議。與傳統黃頁一樣,你可以搜索提供所需服務的公司,閱讀以瞭解所提供的服務,然後與某人聯繫以獲得更多信息。

 

趣味理解

Web Service好比一個服務供應商,給其他廠家提供基礎服務,其他廠家再將這個服務包裝成自己的產品或者服務提供給別人或自己使用。有點像OEM了。既然兩個公司需要合作,不可能靠一句話就可以的,就需要一些標準和規範的東西來實現。那麼:

SOAP 就像兩個公司之間籤的合同,約束雙方按一定規矩和標準辦事。

WSDL 則像說明書,告訴別人你有什麼,能給別人提供什麼服務。

UDDI 好比你的公司需要在黃頁或工商註冊,企業的主營業務登記,方便別人查詢。當然,你也可以不在 UDDI 中註冊,就像在地下室開展業務,靠的是口頭吆喝;但是如果你希望拓展市場,則需要 UDDI 以便能被客戶發現,更方便地找到你。

Web Service是創建可互操作的分佈式應用程序的新平臺。Web Service 的主要目標是跨平臺的可互操作性。爲了達到這一目標,Web Service 是完全基於XML、XSD等獨立於平臺、獨立於軟件供應商的標準的。Web Service在應用程序跨平臺和跨網絡進行通信的時候是非常有用的。Web Service適用於應用程序集成、B2B集成、代碼和數據重用,以及通過Web進行客戶端和服務器的通信的場合。

當然,Web Service也不是萬能的,你不能到處濫用Web Service。在有些情況下,Web Service 會降低應用程序的性能,而不會帶來任何好處。例如,一臺機器或一個局域網裏面運行的同構應用程序就不應該用Web Service 進行通信。

到現在爲止,我們已經討論瞭如何與 Web Service 通信(SOAP),Web Service是怎樣進行說明的(WSDL),以及如何查找 Web Service(UDDI)。這些內容構成了一套基本規範,爲應用程序的集成和聚合提供了基礎。根據這些基本規範,公司可以構建實際的解決方案,並從中獲益。

 

 

7.3  創建簡單的Web Service項目應用

在ASP.NET中創建Web Service和寫一個類文件是很相似的。Web Service是一個以.asmx爲擴展名的文本文件,但其中必須包含一條 @WebService指令,用做聲明。我在這裏向大家講解一個查詢產品價格的Web服務實例,該實例完成的功能相當簡單。但是能對初學者起到很好的指導作用。(完整代碼示例位置:光盤/code/ch07/WebService1)

實現步驟如下。

(1)打開VS.NET,新建一個項目,在左邊的面板中選擇“Visual C#”選項,在右邊的面板中選擇“ASP.NET Web服務應用程序”選項,將其並命名爲“WebService1”,如圖7-1所示。

 

圖7-1  新建ASP.NET Web服務應用程序

(2)單擊“確定”按鈕後,VS.NET就爲我們創建了一個Web服務項目。在新建完項目後,在開發環境中會出現如圖7-2所示的代碼。

圖7-2  Web服務應用程序

在上面的代碼編輯框中,VS已經替我們創建了一個簡單的HelloWorld示例Web服務接口方法,這個方法和我們普通的方法所不同的是帶有[WebMethod]屬性。我們可以註釋掉該方法,然後添加我們自己的業務接口代碼。

(3)實現我們自己的業務代碼。

註釋掉系統自動創建的HelloWorld方法,創建一個查詢產品價格的GetProductPrice方法。

//<summary>
//查詢產品的價格
//</summary>
//<param name="ProductId">產品編號</param>
//<returns>產品價格</returns>
[WebMethod]
public string GetProductPrice(string ProductId)
{
    Products pro = new Products();
    return pro.GetPrice(ProductId);
}


這樣,一個簡單的Web服務就完成了,非常簡單,按下“F5”鍵運行一下看看效果吧。如圖7-3所示。

這個例子非常簡單,因爲僅有一個方法(GetProductPrice)。單擊這個方法會顯示另一個網頁,如圖7-4所示。這一頁就是該特定方法的測試頁,其中包括對應方法接受的每個參數的文本框。現在請在文本框中輸入“001”並單擊“調用”按鈕。

    

            圖7-3  Web服務頁面                            圖7-4  Web服務方法頁面

單擊“調用”按鈕會打開一個新的瀏覽器窗口,其中顯示了一些XML代碼。這些XML代碼是由該Web服務返回的,其中包括了服務的結果。返回的XML代碼如圖7-5所示。

圖7-5  Web服務調用結果

返回的結果是一段XML代碼,客戶端應用程序可以通過對XML的處理,解析其中的數據。

 

7.4  Web Service屬性介紹

每個 Web Service都需要唯一的命名空間,它可使客戶端應用程序區分出可能使用相同方法名稱的 Web Service。在 Visual Studio.NET中創建的Web Service的默認命名空間是“http://tempuri.org/”。儘管命名空間類似於典型的URL,但在Web瀏覽器中是不能查看的,它只是一個唯一標識符。

Web Service(Web服務)提供以下屬性。

l         Description:此屬性的值包含描述性消息,此消息將在XML Web Service的說明文件(例如服務說明和服務幫助頁)生成後顯示給XML Web Service的潛在用戶。

l         Name:此屬性的值包含XML Web Service的名稱。在默認情況下,該值是實現XML Web Service的類的名稱。

l         Namespace:此屬性的值包含 XML Web Service的默認命名空間。XML命名空間提供了一種在XML文檔中創建名稱的方法,該名稱可由統一資源標識符(URI)標識。使用XML命名空間,可以唯一標識XML文檔中的元素或屬性。因而,在 XML Web Service的服務說明中,Namespace被用做與XML Web Service直接相關的 XML 元素的默認命名空間。如果不指定命名空間,則使用默認命名空間 http://tempuri.org/。

以下示例代碼說明了Web Service屬性的用法:

//<summary>
//Service1 的摘要說明
//</summary>
[WebService(Namespace = "http://tempuri.org/",
    Description = "接口的描述說明文字-測試。",
    Name = "LTPService")] //Web Service 的名稱
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
}


WebMethod(Web服務方法)有以下6個屬性。

l         Description:是對Web Service方法的描述信息。就像Web Service方法的功能註釋,可以讓調用者看見的註釋。

[WebMethod(Description="根據產品編號查詢產品的價格")]

public string GetProductPrice2(string ProductId)
{
    Products pro = new Products();
    return pro.GetPrice(ProductId);
}
l         EnableSession:指示Web Service是否啓動Session標誌,主要通過Cookie完成,默認爲false。
public static int i = 0;
[WebMethod(EnableSession = true)]
public int Count()
{
    i = i + 1;
    return i;
}


在IE地址欄中輸入:http://localhost/WebService1/Service1.asmx/Count?,刷新看看:

<?xml version="1.0" encoding="utf-8" ?>
  <int xmlns="http://tempuri.org/">1</int>
<?xml version="1.0" encoding="utf-8" ?>
   <int xmlns="http://tempuri.org/">2</int>


//…不停地刷新,Session的值一直存在

l         MessageName:主要實現方法重載後的重命名:

public static int i = 0;
[WebMethod(EnableSession = true)]
public int Count()
{
    i = i + 1;
    return i;
}
[WebMethod(EnableSession = true, MessageName = "Count1")]
public int Count(int da)
{
    i = i + da;
    return i;
}


通過count訪問的是第1個方法,而通過count1訪問的是第2個方法。

l         TransactionOption:指示Web Service方法的事務支持。

由於HTTP協議的無狀態特性,Web Service方法只能作爲根對象參與事務。如果COM對象與Web Service方法參與相同的事務,並且在組件服務管理工具中被標記爲在事務內運行,則Web Service方法可以調用這些COM對象。如果一個TransactionOption屬性爲Required或RequiresNew的Web Service方法調用另一個TransactionOption屬性爲Required 或RequiresNew的Web Service方法,則每個 Web Service方法將參與它們自己的事務,因爲Web Service方法只能用做事務中的根對象。如果異常是從Web服務方法引發的或未被該方法捕獲,則自動放棄該事務。如果未發生異常,則自動提交該事務,除非該方法顯式調用 SetAbort。

①Disabled

指示Web Service方法不在事務的範圍內運行。當處理請求時,將在沒有事務的情況下執行Web Service方法。

[WebMethod(TransactionOption = TransactionOption.Disabled)]

②NotSupported

指示Web Service方法不在事務的範圍內運行。當處理請求時,將在沒有事務的情況下執行Web Service方法。

[WebMethod(TransactionOption= TransactionOption.NotSupported)]

③Supported

如果有事務,則指示Web Service方法在事務範圍內運行。如果沒有事務,則將在沒有事務的情況下創建Web Service。

[WebMethod(TransactionOption= TransactionOption.Supported)] 

④Required

指示Web Service方法需要事務。由於Web服務方法只能作爲根對象參與事務,因此將爲 Web 服務方法創建一個新事務。

[WebMethod(TransactionOption= TransactionOption.Required)]

⑤RequiresNew

指示Web Service方法需要新事務。當處理請求時,將在新事務內創建Web Service。

[WebMethod(TransactionOption= TransactionOption.RequiresNew)] 

這裏我們來看一個例子。

首先在類代碼中添加引用:using System.EnterpriseServices;,然後設置屬性TransactionOption = TransactionOption.RequiresNew。

例如:

[WebMethod(TransactionOption = TransactionOption.RequiresNew)]

public int DeleteProduct(string ProductId)
{
    String deleteCmdSQL = "delete from P_Product where ProductId='" +
        ProductId + "'";
    String exceptionCmdSQL = "DELETE FROM NonExistingTable WHERE
        ProductId='" + ProductId + "'";
    SqlConnection sqlConn = new SqlConnection(
        Maticsoft.DBUtility.PubConstant.ConString);
    sqlConn.Open();
    SqlCommand deleteCmd = new SqlCommand(deleteCmdSQL, sqlConn);
    SqlCommand exceptionCmd = new SqlCommand(exceptionCmdSQL, sqlConn);
    //這個命令正確執行          
    deleteCmd.ExecuteNonQuery();
   
    //這個命令執行時會發生異常,所以,第一個命令會自動回滾。因爲這個方法被設置爲事務模式
    //發生異常時,ASP.NET會自動中斷事務並回滾
    int cmdResult = exceptionCmd.ExecuteNonQuery();
    sqlConn.Close();
    return cmdResult;
}


在上面的示例中,如果數據庫操作引發異常,則事務將自動中止;否則將提交事務。

l         CacheDuration:設置響應應在緩存中保留的秒數。這樣Web Service就不需要重複執行多遍,可以提高訪問效率,而CacheDuration就是指定緩存時間的屬性。

public static int i = 0;
[WebMethod(EnableSession = true, CacheDuration = 30)]
public int Count()
{
    i = i + 1;
    return i;
}


在IE的地址欄裏輸入:http://localhost/WebService1/Service1.asmx/Count?。

刷新它,內容一樣!要使輸出不一樣,需等30秒。因爲代碼要在30秒後才被再次執行,之前返回的結果都是在服務器高速緩存裏的內容。

有兩個問題可以影響ASP.NET 2.0 Web服務應用程序中的輸出緩存。

在ASP.NET 2.0中,測試頁的HTTP方法已從Get更改爲 Post。但是Post通常不進行緩存。如果在ASP.NET 2.0 Web 服務應用程序的測試頁中改爲使用Get,則緩存將正常工作。

此外,HTTP指示用戶代理(瀏覽器或調用應用程序)應該可以通過將“Cache-Control”設置爲“no-cache”以重寫服務器緩存。因此,當 ASP.NET 應用程序找到“no-cache”標頭時,會忽略緩存的結果。

l         BufferResponse:配置Web Service方法是否等到響應被完全緩衝完才發送信息給請求端。普通應用要等完全被緩衝完才被髮送。

 

7.5  ASP.NET如何調用Web Service

在.NET中調用Web Service其實和創建Web Service一樣簡單。(完整代碼示例位置:光盤/code/ch07/ WebAppClient)

實現步驟如下。

(1)首先我們創建一個ASP.NET Web 應用程序。

(2)添加Web Service引用。

在項目上單擊鼠標右鍵,在彈出的快捷菜單中選擇“添加Web 引用”命令,如圖7-6所示,彈出“添加Web引用”對話框,如圖7-7所示的窗口。

     

圖7-6  選擇“添加Web引用”命令                 圖7-7  “添加Web引用”對話框

添加引用分以下3種情況。

l         如果是本解決方案中的Web服務,則選第一個,程序會自動轉向解決方案中的服務地址。

l         如果是本計算機上的Web服務,則系統會自動尋找本機的Web服務,供你選擇。

l         無論哪種情況,其最終目標都是在URL處輸入相應的地址,進行加載,所以,我們可以在URL中輸入Web服務的地址,無論是本地還是公網的都一樣。然後,單擊“前往”按鈕,則會列出Web服務的測試頁和方法描述,同時驗證項目是否能夠使用 Web 服務,如圖7-8所示。

圖7-8  預覽Web 引用

這時,我們在“Web引用名”文本框中,輸入一個名稱,我們將在代碼中使用該名稱以編程方式訪問所選擇的Web服務,單擊“添加引用”按鈕。

(3)此時,項目中多了一個名叫Web References的目錄,如圖7-9所示,自動生成的代理類就放在這裏。

圖7-9  Web引用

(4)單擊工程中的解決方案資源管理器中的“顯示所有文件”按鈕,這時就可以看到那個代理類了,名叫Reference.cs。

(5)在代碼中使用這個代理類基本上和使用本地普通類一樣。

ProductService.LTPService service = new ProductService.LTPService();

string price=service.GetProductPrice("001");

到此爲止,ASP.NET調用Web Service的過程就完成了,整個過程只寫了兩行代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章