[老老實實學WCF] 第六篇 元數據交換

老老實實學WCF

第六篇 元數據交換

 

通過前兩篇的學習,我們瞭解了WCF通信的一些基本原理,我們知道,WCF服務端和客戶端通過共享元數據(包括服務協定、服務器終結點信息)在兩個終結點上建立通道從而進行通信。我們通過手寫代碼(或配置)的方式爲服務端編寫了元數據信息,沒有藉助元數據交換就實現了通信。然而在實際應用中,元數據往往是很多的,而且重複編寫元數據的工作也是不值得的,因此必然會用到元數據交換的方式讓客戶端獲取元數據,本篇我們就來進一步瞭解一下元數據和元數據交換。

 

1. 元數據是怎樣提供的

我們知道,元數據包括了要和服務端進行通信的所有信息,包括服務協定接口、服務端終結點地址、綁定等信息,它指出了客戶端應該到何處去尋找服務以及怎樣調用服務的一切線索。但是服務端是怎樣公佈其元數據的呢?

 

答案是使用WSDL文件,WSDL即Web Service Description Language,Web服務描述語言,它是一個XML文件,在這個文件中按照一定的標準來對Web Service進行描述,他是符合W3C標準的,因爲WCF是被設計爲供不同平臺調用的服務框架,所以客戶端可能是非微軟平臺的,比如Java什麼的。因此WCF必須使用WSDL這種國際標準的描述方法來描述服務才能被衆多的平臺所訪問。

2. 元數據交換的過程是怎樣的

在WCF服務端的運行時,有一組類庫隨時待命把服務的元數據輸出爲WSDL描述提供給請求者,只要有客戶端按照服務端約定的方法來請求元數據,服務端立即將服務運行時狀態寫成WSDL文件提供。客戶端得到的實際上就是WSDL文件(還有一些框架描述文件XSD),客戶端拿到文件後再使用自己的方法來解讀WSDL,把他翻譯成客戶端可用的源代碼或配置文件,這時客戶端就得到了服務的編程模型,通過一些代理類,客戶端甚至可以像調用本地對象一樣使用WCF服務。

 

因此整個過程是這樣:客戶端向服務端請求元數據交換-->服務端運行時將元數據編寫成WSDL文件提供-->客戶端獲得文件-->客戶端翻譯文件-->客戶端根據翻譯結果生成本地類代碼和配置-->客戶端獲得服務的本地編程模型。

 

這就是元數據交換的過程。

3. 獲得WSDL

 在微軟平臺中,有兩種方法來進行元數據交換,第一是使用服務引用,第二是使用元數據實用工具(svcutil.exe)來進行,我們先學習這個工具。

這個工具可以在Windows SDK中找到,具體位置爲 C:\Program Files\Microsoft SDKs\Windows\v6.0\Bin,如果你有VS2010,可以啓動VS2010的命令行工具,這樣就可以在任何目錄下使用這個程序。

 

我們先看一個例子,就是我們在前幾篇中建立的IIS服務HelloWCFService,它被我寄宿在IIS中。

源代碼如下(HelloWCF.cs):

using System;
using System.ServiceModel;

namespace LearnWCF
{
    [ServiceContract]
    public interface IHelloWCF
    {
        [OperationContract]
        string HelloWCF();
    }

    public class HelloWCFService : IHelloWCF
    {
        public string HelloWCF()
        {
            return "Hello WCF!";
        }
    }
}


配置文件(web.config)如下:

<configuration>
  <system.serviceModel>
    <services>
      <service name="LearnWCF.HelloWCFService" behaviorConfiguration="metadataExchange">
        <endpoint address="" binding="wsHttpBinding" contract="LearnWCF.IHelloWCF"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataExchange">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

 

在瀏覽器中輸入服務地址會如下圖所示:

 

看到系統提示的那行命令了麼?系統在告訴我們如何使用svcutil.exe來獲得元數據。我們現在試一下,首先打開VS2010命令行:

開始-->所有程序-->Visual Studio 2010-->Visual Studio Tools-->Visual Studio命令行提示

命令行工具的窗口是這樣的:

 

我們導航到一個目錄下準備獲得元數據文件。

我們暫時不按照瀏覽器提供給我們的方法做,因爲按照那個方法做就把獲得WSDL和翻譯WSDL爲客戶端代碼合在一起了,我們先獲得WSDL元數據文件,看看它是什麼樣子的。我們按如下的指令做:

svcutil.exe /t:metadata http://localhost/iisservice/hellowcfservice.svc?wsdl

我們加入了一個參數/t:metadata 表示只輸出元數據,不生成代碼。命令的執行過程如下:


可以看到生成了3個文件,包括兩個架構文件和一個WSDL文件,這些就是服務端元數據的描述了,所有的客戶端請求到的實際上都是這個文件。WSDL的規範比較多,關於它的內容,我們今後再展開來看,不過簡單的打開看一下就能看出一些與服務協定、綁定、操作這些東西相關的地方。

4. 翻譯WSDL文件

WSDL是一個XML文件,其實就是個文本文件,客戶端必須將其按照自己的平臺特點把他翻譯成本地代碼文件來使用。svcutil當然會提供這個功能。在wsdl文件所在目錄下使用如下的命令就可以把WSDL文件翻譯成本地代碼文件:

svcutil *.wsdl *.xsd

顧名思義,就是根據當前目錄下的所有的WSDL文件和XSD文件來生成客戶端代碼文件。過程會是這樣:

 

可以看到,生成了一個cs文件和一個配置文件,這些就是根據WSDL文件翻譯成的客戶端代碼文件了。打開來看看,一定不陌生,就是使用ClientBase<>來生成一個客戶端代理類並把終結點的信息配置在了.config文件裏。把這兩個文件包含在客戶端的項目中並把output.config改成app.config就可以了。

4. 更好地使用元數據交換工具

之前我們瞭解了使用svcuitl.exe來獲取WSDL並翻譯成客戶端代碼的過程。實際上這兩步可以合二爲一。直接執行下面的命令可以直接獲得客戶端文件:

svcutil.exe http://localhost/iisservice/hellowcfservice.svc?wsdl

這樣它就不會生成WSDL而直接生成客戶端文件了。

不過按照這樣的方式生成的文件可能不太符合我們的要求,我們可以加上一些參數來指定我們輸出的文件名:

svctuil.exe /out:ClientProxy.cs /config:app.config http://localhost/iisservice/hellowcfservice.svc?wsdl

這樣輸出的文件我們就可以直接包含在客戶端項目中使用了。

5. 使用服務引用

其實使用服務引用跟使用svcutil.exe生成的客戶端模型是一樣的,不過服務引用保留了WSDL文件(以及一些相關的七七八八的文件),沒有svcutil.exe來得那麼清爽,但是它跟VS2010集成,使用起來很簡單,而且當服務發生變化時,只需要右擊服務引用選擇更新服務就可以重新下載WSDL了。

6. 展開一點點

作爲服務端,公開元數據是需要配置的,不同的配置會導致元數據公開的方式不同。

我們要記住,WCF服務端公開元數據必須具備兩個條件:

(1) 爲服務添加ServiceMetadata行爲。

(2) 打開元數據交換終結點。

二者缺一不可。

 

WCF的公開元數據的手段主要有兩種:

第一種:通過HTTP GET方法。

這就是在前文中我們看到的方法,我們可以使用HTTP Get的方法來獲得WSDL文件即在服務地址.svc後面跟上?wsdl的方法直接請求到WSDL文件。我們可以直接在瀏覽器中輸入服務端地址.svc?wsdl,瀏覽器就直接獲得了WSDL文件併爲我們顯示出來了。

 

還有相應的框架描述文件(XSD)

 

 

如果想採用這種元數據公開方式,必須配置服務的ServiceMetadata行爲,並指定httpGetEnabled = "true",而元數據公開終結點不必配置,系統會自動配置一個,配置文件的寫法如下:

<configuration>
  <system.serviceModel>
    <services>
      <service name="LearnWCF.HelloWCFService" behaviorConfiguration="metadataExchange">
        <endpoint address="" binding="wsHttpBinding" contract="LearnWCF.IHelloWCF"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataExchange">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

在這種配置下,訪問元數據的方法是訪問下面的地址:

http://localhost/iisservice/hellowcfService.svc?wsdl


第二種:通過MEX元數據交換終結點。

在這種方式下,我們首先要保證服務擁有ServiceMetadata行爲,但是httpGetEnabled可以不必爲true。此外我們還需要爲服務顯式地添加一個終結點,這個終結點的地址、綁定和協定都是指定的我們不能更改

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

配置文件的寫法如下:

<configuration>
  <system.serviceModel>
    <services>
      <service name="LearnWCF.HelloWCFService" behaviorConfiguration="metadataExchange">
        <endpoint address="" binding="wsHttpBinding" contract="LearnWCF.IHelloWCF"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataExchange">
          <serviceMetadata />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

 

如果按這種配置,我們必須按照如下地址來訪問公開的元數據

http://localhost/iisservice/hellowcfservice.svc/mex


注意,由於沒有開啓HTTP GET,我們不能在瀏覽器中直接輸入這個地址來獲取WSDL了(會提示400錯誤),我們必須通過svcutil.exe或添加服務引用的方式來訪問。

 

使用svcutil.exe或服務引用的時候可以不關心元數據公開方式是HTTP GET還是Mex,他們會自動尋找到合適的方式,只需要把服務的svc文件地址輸入就可以了,但是我們應該知道,這兩種元數據公開的方式是有區別的。

6. 總結

通過今天的學習,我們進一步瞭解了WCF元數據的和元數據交換的原理。雖然我們在實際工程中都會並且應該使用元數據交換工具來幫助提高效率,但是這背後發生的所有環節也是我們應該掌握的。

 

相關資源

MSDN關於Svcutil.exe用法的文檔

http://msdn.microsoft.com/zh-cn/library/aa347733.aspx




 

 

 

 

 

 

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