程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 《WCF技術內幕》29:第2部分_第5章_消息:使用消息頭(下)

《WCF技術內幕》29:第2部分_第5章_消息:使用消息頭(下)

編輯:關於.NET

WS-Addressing 和MessageHeaders類型

在前面“MessageHeader類型”一節,我們已經學習了使用 MessageHeader表 一個WS-Addressing終結點。我們會很少手動編寫代碼來使用一個MessageHeader 去表示WS- Addressing終結點,因為MessageHeaders類型定義了幾個表示一個終 結點引用的屬性。換句話說,MessageHeaders定義了幾個可以增加、修改和刪除 WS-Addressing消息頭塊的方法,並且這個是給Message實例設置消息頭塊的主要 方法。

更確切地說,MessageHeaders類型定義了以下與終結點相關的屬性:From, ReplyTo, FaultTo, and To。From、ReplyTo和FaultTo是EndpointAddress的屬 性。如前面提到的一樣,EndpointAddress類型是對於WS-Addressing 終結點規 范定義的CLR抽象。我們會在下一節裡詳細學習EndpointAddress類型。根據WS- Addressing規范裡的定義,To是Uri類型的屬性。

MessageHeaders類型同樣定義了與其它WS-Addressing規范相關的屬性。例如 ,Action、MessageId和RelatesTo屬性映射到相似名字的WS-Addressing消息頭 塊上。Action是String類型,而且非常簡單。概括地說,當屬性設置完畢,WS- Addressing Action也會在Message序列化的時候序列化。

MessageId和RelatesTo屬性是UniqueId類型的,而且也很簡單。UniqueId類 型很像GUID,但是它借助重載的構造函數,可以使用其它類型。思考下面的代碼 :

UniqueId uniqueId = new UniqueId();
Console.WriteLine(uniqueId.ToString());
uniqueId = new UniqueId("myuniquevalue");
Console.WriteLine(uniqueId.ToString());

運行代碼,產生以下輸出:

urn:uuid:
myuniquevalue

注意UniqueId對象的值可以是GUID類型的值,也可以是任意String的值。這 是個必要的功能,因為MessageId 和RelatesTo  WS-Addressing消息頭塊是 xs:Uri類型。換句話說,任何值都可以在這裡替換。因為WCF遵循WS-Addressing 規范,System.Guid不能表示這些屬性。

EndpointAddress類型

EndpointAddress類型由兩個功能:它可以方便地保存目標地址的信息,並且 它是一個序列化WS-Addressing終結點到Message裡的方式。換句換說, EndpointAddress類型是經常使用的API之一,但是它同樣在Message序列化和反 序列化裡起著重要作用。

EndpointAddress包裝了一個System.Uri對象。因此,所有的 EndpointAddress構造函數某些形式上,都接受一個System.Uri參數。更進一步 說,6個構造函數裡有5個接受一個Uri參數,另外一個接受String參數。但是這 個構造函數會從此String參數來構造一個Uri然後調用其它的一個構造函數。 EndpointAddress這個特性使得類型更加好用,如下所示:

EndpointAddress address1 = new
  EndpointAddress("http://wintellect.com/OrderStuff");
Console.WriteLine("Address1: {0}",address1.ToString());

EndpointAddress address2 = new EndpointAddress(
  new Uri("http://wintellect.com/OrderStuff"));
Console.WriteLine("Address2: {0}", address2.ToString());

Console.WriteLine("address1 {0} address2",
  (address1 == address2) ? "equals" : "does not  equal");

運行代碼,產生以下輸出:

Address1: http://wintellect.com/OrderStuff
Address2: http://wintellect.com/OrderStuff
Address1 equals Address2

注意到ToString方法返回是Uri的String形式,而不是一個序列化的 EndpointAddress。同樣也看到2個構造函數創建了等價的EndpointAddress對象 。(在EndpointAddress類型上的重載操作符為了相等性檢查對象的內部狀態。 )

還有幾個其它的重載構造函數接受一個AddressHeader、 AddressHeaderCollection、EndpointIdentity和 XmlDictionaryReader類型的 參數。最值得注意的是AddressHeader類型的參數,而這個就是我們接下來的內 容。

AddressHeader類型

AddressHeader類型是CLR對於一個WS-Addressing參數的抽象,它簡化在序列 化之前,添加參數到Message的工作,同樣也包括反序列化之後獲取引用參數的 值。當第一次接觸AddressHeader類型的時候,可能會和MessageHeader類型

從對象模型角度來看,AddressHeader類型與Message和MessageHeader很相似 ,因為它也是一個抽象類型,並且定義了幾個工廠方法,Write 和Get 方法。( MessageHeader沒有定義Get方法。)AddressHeader類型裡的這些方法是為了與 Message 和MessageHeader保持一致性,但是不能保證重復。如果你願意的話, 我會把這些方法的實驗任務留給你。

序列化一個EndpointAddress對象

當被Message 對象引用的時候,EndpointAddress非常有用。這經常是通過 Message類型的Headers屬性來完成。比如,我們可以實例化一個 EndpointAddress並且賦值給Message的FaultTo屬性。例如:

String uriValue = "http://wintellect.com/someService";
AddressHeader header = AddressHeader.CreateAddressHeader("ref  param");
EndpointAddress address = new EndpointAddress(new Uri (uriValue),
  new AddressHeader[1] { header }); // notice the use of  the AddressHeader

Message myMessage = Message.CreateMessage(
  MessageVersion.Soap12WSAddressing10, "urn:SomeAction", "Hello  There");
myMessage.Headers.FaultTo = address;
Console.WriteLine(myMessage.ToString());

運行代碼,產生以下輸出:

<s:Envelope  xmlns:a="http://www.w3.org/2005/08/addressing"  xmlns:s="http://www.w3.org/2003/
05/soap-envelope">
  <s:Header>
     <a:Action  s:mustUnderstand="1">urn:SomeAction</a:Action>
     <a:FaultTo>
       <a:Address>http://wintellect.com/someService</a:Address>        <a:ReferenceParameters>
        <string  xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
          ref param
        </string>
       </a:ReferenceParameters>
     </a:FaultTo>
  </s:Header>
  <s:Body>
     <string  xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
       Hello There
     </string>
  </s:Body>
</s:Envelope>
     <string a:IsReferenceParameter="true"
             xmlns="http://schemas.microsoft.com/203/10/Serialization/">
       ref param
     </string>
  </s:Header>
  <s:Body>
     <string  xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
       Hello There
     </string>
  </s:Body>
</s:Envelope>

注意到AddressHeader 賦值給WS-Addressing終結點的FaultTo屬性。

因為WS-Addressing裡的To消息頭塊是一個xs:uri,想知道如何在至關重要的 消息頭裡使用EndpointAddress類型也很正常。正如你之前看到的, MessageHeaders的To屬性接受一個 System.Uri參數,所以我們不能使用 EndpointAddress直接設置To屬性。EndpointAddress 定義了ApplyTo實例方法來 解決這個問題。ApplyTo方法接受一個Message類型的參數,並且把 EndpointAddress的值賦值給Message,如下所示:

String uriValue = "http://wintellect.com/someService";
AddressHeader header = AddressHeader.CreateAddressHeader("ref  param");
EndpointAddress address = new EndpointAddress(new Uri (uriValue),
  new AddressHeader[1] { header }); // notice the use of  the AddressHeader

Message myMessage = Message.CreateMessage(
  MessageVersion.Soap12WSAddressing10, "urn:SomeAction", "Hello  There");

address.ApplyTo(myMessage);
Console.WriteLine(myMessage);

運行代碼,產生以下輸出:

<s:Envelope  xmlns:a="http://www.w3.org/2005/08/addressing"
  xmlns:s="http://www.3.org/2003/05/soap-envelope">
  <s:Header>
     <a:Action  s:mustUnderstand="1">urn:SomeAction</a:Action>
     <a:To  s:mustUnderstand="1">http://wintellect.com/someService</a:To>
     <string a:IsReferenceParameter="true"
             xmlns="http://schemas.microsoft.com/203/10/Serialization/">
       ref param
     </string>
  </s:Header>
  <s:Body>
     <string  xmlns="http://schemas.microsoft.com/2003/10/Serialization/">
       Hello There
     </string>
  </s:Body>
</s:Envelope>

注意到EndpointAddress(包括AddressHeader)賦值給Message對象,並且每 個引用參數都符合WS-Addressing規范。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved