WCF專題系列(2):深入WCF尋址Part 2—自定義尋址報頭
[2] WCF專題系列(1):深入WCF尋址Part 2
概述
在WCF專題系列(1):深入WCF尋址Part1一文中,我們對Web服務尋址規范做了一些認識,了解了終結點引用和消息信息報頭兩種結構,該規范在Web服務中的地位舉足輕重,后續我們會經常提到該規范。在本文中,我們將繼續深入WCF尋址的內容,包括元數據中的終結點地址,自定義尋址標頭等相關信息。
終結點地址定義
了解了Web服務尋址規范,再回到WCF,在WCF中,終結點地址是由EndpointAddress類來表示的,它其中很重要的幾個部分是:一個表示服務地址的統一資源定位符 (URI),一個表示服務的安全標識的 Identity 和一個可選的 Headers 集合,其中Headers用于標識終結點或與終結點交互的更多詳細尋址信息。如圖1所示:
圖1
記的我在WCF專題系列(1):深入WCF尋址Part1一文提到過,每個終結點引用都可以包含一些添加額外標識信息的引用參數,即尋址標頭,在 WCF 中,將這些引用參數建模為 AddressHeader 類的實例,這里的Headers屬性就是這些實例的集合,可以通過AddressHeader類提供的靜態方法CreateAddressHeader來創建一個AddressHeader實例,如下代碼所示:
AddressHeader header = AddressHeader.CreateAddressHeader("basic", "http://www.cnblogs.com/terrylee", "Terrylee");
指定終結點地址
在WCF中提供了基址技術,這使的我們在指定終結點地址時可以酌情選用相對地址或者絕對地址,指定絕對地址的方法是在終結點定義中提供完全限定的地址,如下代碼所示:
<service name="TerryLee.WCFAddressing.Service.CalculatorService" behaviorConfiguration="calculatorBehavior"> <endpoint address="http://localhost:8887/CalculatorService" binding ="basicHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> </service>
使用絕對地址固然簡單,但是如果我們的服務需要公開多個終結點,而這些終結點地址又具有相同的基地址時,也許相對地址是更好的選擇。在創建服務宿主對象時,提供一個基地址,如下代碼所示:
using (ServiceHost calculatorServiceHost = new ServiceHost(typeof(CalculatorService), new Uri("http://localhost:8887/CalculatorService"))) { calculatorServiceHost.Opened += delegate { Console.WriteLine("Service begin to listen via the Address:{0}", calculatorServiceHost.BaseAddresses[0].ToString()); }; calculatorServiceHost.Open(); Console.Read(); }
又或者同時在配置文件中指定基地址,這樣就無須在每個終結點中指定絕對地址了,如下代碼所示:
<service name="TerryLee.WCFAddressing.Service.CalculatorService" behaviorConfiguration="calculatorBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8887/Calculator"/> </baseAddresses> </host> <endpoint address="myservice1" binding ="basicHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> <endpoint address="myservice2" binding ="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> </service>
但請注意,基址技術是為我們在配置終結點時提供了方便,客戶端對它是毫無所知的,客戶端看到的仍然是絕對地址,在打開服務宿主時,它會匹配所有的相對地址,從而為每個終結點提供相應的絕對地址,如上面的示例,可以在WSDL中看到:
<wsdl:service name="CalculatorService"> <wsdl:port name="BasicHttpBinding_ICalculator" binding="tns:BasicHttpBinding_ICalculator"> <soap:address location="http://localhost:8887/Calculator/myservice1" /> </wsdl:port> <wsdl:port name="WSHttpBinding_ICalculator" binding="tns:WSHttpBinding_ICalculator"> <soap12:address location="http://localhost:8887/Calculator/myservice2" /> <wsa10:EndpointReference> <wsa10:Address>http://localhost:8887/Calculator/myservice2</wsa10:Address> <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity"> <Upn>TerryLee-PC\TerryLee</Upn> </Identity> </wsa10:EndpointReference> </wsdl:port> </wsdl:service>
如果在指定了基地址的情況下,有以下幾種情況:指定相對地址為空,終結點地址與基地址相同;指定相對地址不為空,追加相對地址到基地址上;指定一個絕對地址,基地址不起作用,終結點地址仍然為指定的絕對地址;指定一個絕對地址和一個與基地址不同的綁定,基地址不起作用。現在有這樣一段配置信息:
<service name="TerryLee.WCFAddressing.Service.CalculatorService" behaviorConfiguration="calculatorBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8887/Calculator"/> </baseAddresses> </host> <endpoint address="" binding ="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> <endpoint address="myservice2" binding ="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> <endpoint address="http://localhost:8886/CalculatorService" binding ="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> <endpoint address="net.tcp://localhost:8885/Calculator" binding ="netTcpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> </service>
可以在ServiceHost啟動后,輸出所有的終結點地址和綁定信息,如下代碼:
ServiceDescription desc = calculatorServiceHost.Description; foreach (ServiceEndpoint endpoint in desc.Endpoints) { Console.WriteLine("Endpoint - address: {0}", endpoint.Address); Console.WriteLine(" binding: {0}", endpoint.Binding.Name); Console.WriteLine(" contract: {0}", endpoint.Contract.Name); }
輸出結果如圖2所示:
圖2