本文假定你對Visual StudioNET和XML技術都比較熟悉
摘要
Web服務是利用XML消息來傳遞數據的技術如果你要設計一個數據庫結構你大概不會讓你的工具去自動的完成而是要手工的進行調整來保證最高的效率作者在這篇文章中認為設計Web服務也是一樣的你需要首先了解Web服務會返回什麼樣的數據然後再用這樣的數據結構來設計出最有效率的消息格式你將從這篇文章中學習到如何決定有效的消息結構並且根據這一結構來創建相關的Web服務
沒有經驗的開發者在開發Web服務時經常跳過設計這一重要的第一步他們從給工程添加Web引用開始然後再給服務中添加相應的Web方法雖然這種方法比較簡便卻不是創建真正用於業務的Web服務的好辦法因為這樣的話就忽略了Web服務消息結構的設計在這篇文章中我會向大家解釋為什麼這種常規的辦法不適合重要的開發然後會教給大家用Visual Studio® NET設計Web服務的更好辦法
對你的數據有把握
當編寫面向數據的應用時如何去創建數據庫結構呢?你是不是會先設計出類程序然後再讓你的集成開發環境幫你自動創建數據庫結構還是你會親自手動創建標准化的完整的和高效的數據庫結構?一般情況下你都會選擇手動的來創建數據庫結構即使你是利用了可視化的數據結構設計器而不是使用數據定義語言(DDL)來進行設計你依然對數據結構的設計有良好的控制
Web服務的目標就是在恰當的時候提供恰當的數據當客戶端調用Web服務時XML格式的消息被用於發送請求和返回結果當編寫Web服務和相應的客戶端程序時你主要就是針對這些消息格式編程應用程序真正關心的就是這些消息中承載的數據既然如此為什麼要先設計出Web服務的類和方法然後再用工具自動的生成消息的數據結構?你應該先設計出消息的數據結構然後再根據這一結構來設計Web服務就像你在設計數據庫結構時一樣
消息而不是方法
優先考慮消息是一個進步例如某個Web服務接收地區編碼然後返回當地的天氣情況習慣了面向對象的方法你會自然而然的就設計出GetWeather方法來獲取字符參數然後返回一個CurrentWeather對象的實例(參見示例)
這種方法不是很好因為你設計的這些方法和對象僅對你這個Web服務有意義使用這個Web服務的程序對你設計的CurrentWeather類卻一無所知例如類成員所表示的具體意義事實上客戶程序僅僅知道它接收了一個名叫CurrentWeather的XML架構(XSD)復雜類型當你訪問Web服務的WSDL說明(形如weatherserviceasmx?wsdl)時會自動的創建這一XSD類型的定義客戶端工具就會根據自身的情況將這一XSD類型映射成為數據結構例如SOAP工具會把CurrentWeather實例映射成為IXMLDOMNodeList接口的XML節點NET Framework通常會把這個XSD類型轉換成為本地類型從而帶來很多麻煩例如增加了對示例中Web服務引用應用會根據CurrentWeather的XSD類型自動生成一個名叫CurrentWeather的類
public class CurrentWeather
{
public string Conditions;
public string IconUrl;
public Single Humidity;
public Single Barometer;
public float FahrenheitTemperature;
}
對那些不知道這一Web服務功能的人來說第一個問題就是CelsiusTemperature屬性哪裡去了為什麼FahrenheitTemperature是一個域而不是屬性?答案就是只有服務內CurrentWeather類的公共可讀寫的成員會被NET Framework自動序列化成為XML因為CelsiusTemperature是只讀的它就沒有被序列化也就不能在客戶端的CurrentWeather類中體現出來而且自動生成的客戶端類只包含公共域而不是屬性客戶端程序僅僅知道有名叫CurrentWeather的XSD類型但XSD類型並沒有區分屬性和域對於客戶端來講都只是數據
從這個角度看你會覺得Web服務有著很嚴重的局限性不能夠讓客戶端得到服務所返回對象的實例這其實並不是Web服務的局限而只是你不能把Web服務看成是獲取遠程對象(就像DCOM一樣)的手段的原因
設計天氣服務的更好辦法是從定義消息開始例如你定義了WeatherRequest消息包含有地區編碼和包含有當地天氣情況的CurrentWeather消息示例就體現了示例的請求和返回消息可以作為你設計Web服務的起點
現在由於Web服務和客戶端的開發者都有可以理解這一Web服務的WeatherRequest消息和CurrentWeather消息他們就不再會被一些實現細節所困惑了例如只讀成員和屬性等
格式化消息的設計
現在你已經創建了樣例的請求和返回消息你需要把這些消息的設計格式化以便Visual Studio NET等開發工具可以理解這些設計並且提供更加強大的開發功能如客戶代理生成
你需要去創建一個XML架構來描繪你的請求和返回消息從而格式化這些消息的設計雖然你可以用很多種的工具甚至文本編輯器來生成這些XML架構文件我還是建議你使用Visual Studio的XML架構編輯器
使用XML架構編輯器啟動Visual Studio並且選擇菜單 新建 | 文件 | XML架構設計器有一個專門的工具箱面板裡面包含有XML架構的組件例如元素聲明和類型定義等想聲明WeatherRequest一類的元素只需要把元素(Element)圖標從工具箱中拖到設計界面上就可以了每個元素都包含有兩個必須設置的主要屬性元素的名稱和數據類型當你設置元素的數據類型時你可以從XSD內置的類型中選擇也可以自定義類型例如WeatherRequest就是內置的字符串類型(WeatherRequest元素包含字符串)而CurrentWeather則是包含有其他元素的自定義類型
對類型進行定義然後再聲明這些類型的具體元素這和你在編程時所作的工作非常類似先定義類(例如CurrentWeather類)然後就成為你工程裡的一個新的類型隨後你就可以對這些類聲明變量了就像示例中的cw變量
XML架構設計器使聲明新的類型變得容易通過在CurrentWeather元素的界面內增添行的方式就可以定義新的CurrentWeather類型就如示例展示的那樣CurrentWeather元素包含有未命名的類型這個類型包含有ConditionsIconUrlHumidityBarometerFahrenheitTemperature和CelsiusTemperature元素
示例Visual Studio XML架構設計器
到此為止就還有最後一步來完成消息的設計你要為XML架構設置targetNamespace屬性來唯一的標識你的Web服務或應用程序就像在示例種屬性窗口中的設置一樣這是一個良好的習慣但它不是必須的以致於很多開發者都忽略了這重要的一步
如過你需要對XML架構進行深入的工作你可以通過點擊示例中底部的XML附簽來切換到XML視圖它展現了整個XML架構的源文件你可以根據需要對它進行深入的編輯就像示例那樣
示例消息架構
完成界面的定義
示例中的XML架構充分描述了請求和返回消息的數據定義但消息還有很多其他方面的信息需要被用一種正式的機器可讀的方式所描述出來例如消息是否使用了SOAP遠程調用?消息是怎樣被編碼的?為了提供這些方面的信息你可以創建Web服務描述語言(WSDL)文件現在Visual Studio NET裡還沒有內置的WSDL設計器不過有第三方的產品可以提供圖形用戶界面的WSDL設計器而且WSDL是符合XML語法的你可以用任何的XML或者是文本編輯器來創建WSDL文件由於需要提供大量的特性所以WSDL語法會有一些復雜但實際上你只會用到其中很小的一部份你最好建立一個WSDL模板文件(類似示例中的那樣)然後在其基礎上修改來滿足你的需要
示例展示了為天氣服務定制的WSDL模板文件我修改了請求與返回消息中的部分信息指向在ServiceMessages架構中設計的WeatherRequest和CurrentWeather元素還把操作命名為GetWeather把綁定命名為WeatherInterface這些命名都會在你的代碼中分別作為Web方法名稱和綁定名稱所以盡量使名稱有良好含義
到此為止就完成了設計的工作你現在准備好了Web服務界面的正式設計包括每個請求和返回消息中的應用程序數據的定義接下來服務的開發者就應該開始實現這些接口的功能客戶端的開發者也要進行相應的編程了清注意客戶端的開發者不需要等到服務開發完成後才能開始開發工作這意味著你可以通過讓兩種開發同時進行來節省時間
接口的實現
你可以使用Microsoft® NET Framework SDK中的wsdlexe工具來實現一個Web服務的接口這一命令行工具可以對WSDL文件進行操作生成Web服務的stub類(實現了給定接口的類)或代理類(客戶端使用的類)
例如想要生成天氣服務接口的stub類你可以運行wsdlexe後面加/server開關傳遞給它接口的WSDL地址如下面這樣
C:\> wsdlexe /server /o:WeatherStubcs
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) NET Framework Version ]
Copyright (C) Microsoft Corporation All rights reserved
Writing file WeatherStubcs
默認的wsdlexe會生成C#代碼如果你可以使用/language開關來選擇生成Visual Basic® NET或JavaScript語言在這個例子中生成的WeatherStubcs文件包含一個抽象的WeatherInterface類來實現天氣的接口這個類包含一個GetWeather方法它可以接受一個字符串參數然後返回一個CurrentWeather的實例CurrentWeather類是根據在XML架構中的CurrentWeather類型而生成的
開始實現服務代碼的時候把WeatherInterface類加入到你的工程中創建一個新的Web服務然後把這個Web服務改成從WeatherInterface抽象類繼承然後你就可以重寫基類的GetWeather方法實現你的業務邏輯就像示例那樣為了通過SOAP展現這個GetWeather方法你需要加入一個WebMethod屬性來明確這個GetWeather方法就是較早前在WeatherInterfacewsdl定義的那個GetWeather操作的具體實現你還需要在返回的信息中加入一個Xml元素添加一個SoapDocumentMethod屬性並且把它的ParameterStyle屬性設置成為SoapParameterStyleBare(請參見示例)
如果你使用Visual Basic NET開發你不用手動的添加這些屬性當你從overrides菜單中選擇GetWeather 方法時Visual Studio就會自動地把它們添加在你的代碼裡
如果你編寫了Web服務並且找到那個自動生成的WSDL文件你會發現裡面包含了很多的信息這確實是個麻煩首先WSDL文件裡面包含完整的WeatherInterface其次文件還包含了支持HTTP GET和HTTP POST協議的另外兩個接口
包含有完整的接口會影響單一接口多次實現的目標所以你首先要從服務的WSDL文件中刪除那些接口的內容然後確保它指向你先前創建的WeatherInterfacewsdl文件想達到這一目的你需要給Web服務本身增加一個WebServiceBinding屬性指出服務實現的WSDL綁定(WeatherInterface綁定)的名稱以及定義綁定的WSDL文件的地址你還需要設定每個Web方法的SoapDocumentMethod屬性的綁定屬性指出這些Web方法在綁定中定義的具體操作示例展示了經過這些修改的Web服務
最後我建議你關閉服務的WSDL文件中綁定的HTTP GET和HTTP POST如果是為某些特定的應用程序關閉這些協議你只要編輯應用的nfig文件在systemweb節中增加webServices節即可如下所示
<webServices>
<protocols>
<remove name=HttpGet/>
<remove name=HttpPost/>
</protocols>
</webServices>
你也可以通過編輯nfig文件來對整個計算機關閉以上的協議從協議列表中刪除HttpGet和HttpPost即可
現在當你創建了Web服務並且查看其WSDL文件時你得到了一個簡潔的文件僅僅引入了WeatherInterfacewsdl文件並且添加了服務定義(參見示例)你可以把服務定義也看成是WeatherInterfacewsdl中定義接口的特殊實現
對界面編程
開發客戶端程序來實現天氣接口你可以使用wsdlexe或者是在Visual Studio裡添加Web引用來從接口生成代理類注意當你生成這個類時你需要指出WeatherInterfacewsdl因為裡面包含著接口信息特別當類中沒有實現這些接口的服務的地址時因此客戶端必須在設計時和運行時都設置這一地址避免在客戶端代碼中寫死這個地址你最好把它放置在你客戶端的配置文件中在運行時動態讀取就可以了以下就是WeatherInterface的客戶端代碼
Private Sub btnWeather_Click( _
ByVal sender As SystemObject _
ByVal e As SystemEventArgs) Handles btnWeatherClick
Dim ws As New localhostWeatherInterface()
wsUrl = SystemConfiguration _
ConfigurationSettingsAppSettings(ServiceUrl)
Dim cw As localhostCurrentWeather = _
wsGetWeather()
End Sub
總結
Web服務是利用XML消息來傳遞數據的技術所以編寫Web服務的時候尤其要精心的用XML架構和WSDL來設計消息的結構當你從設計消息結構開始而不是從編寫方法開始的時候你的Web服務需要接收和返回何種類型的數據就變得比較清晰了使用XSD和WSDL來設計消息結構你可以創建一個標准的接口定義讓Web服務的開發者去實現同時客戶端的開發者也可以參照其來進行編程下次你再開發Web服務的時候請先用Visual Studio XML架構設計器來設計消息的結構吧
From:http://tw.wingwit.com/Article/program/net/201311/13128.html