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

《WCF技術內幕》25:第2部分_第5章_消息:創建一個消息(下)之MessageFault

編輯:關於.NET

Message和SOAP Fault

Message類型定義了一些用來創建表示SOAP Fault消息對象的工廠方法。SOAP Fault是SOAP消息的一種形式,它用來表示錯 誤信息。在SOAP規范(1.1 和1.2)對於消息體內容,並且某些時候,關於SOAP 消息頭塊的規定都存在差別。Message是對於SOAP消息的CLR抽象,Message可以 表示SOAP Fault,和表示一個SOAP消息一樣。本節會描述一些SOAP Fault的基本 概念和創建表示SOAP Fault消息的基本類型以及如何創建一個表示SOAP Fault的 Message實例。
SOAP Fault 剖析

SOAP Fault遵守SOAP規范(1.1 和1.2)。根本上,SOAP1.1 Fault包含一個SOAP body,body裡包裝了一個必須 的faultcode老徐備注2、faultstring元素,還有一個可選的faultactor和 faultdetail元素。為了避免重復敘述這些規范,你可以在這裡 http://www.w3.org/TR/soap11找到更多的可選擇元素的消息規范。在更高層次 上,faultcode表示一個標識符,接受者和發送者可以用來辨別錯誤SOAP1.1 規 范,定義了一個faultcode的小集合,但是程序可以定義自己使用的唯一的 faultcode。Faultstring表示一種人工可讀的 faultcode,它不是要給接收程序 (除非你想吧Faultstring顯示給用戶)。Faultcode是一個描述錯誤來源的URI 。

SOAP Fault 從SOAP 1.1到SOAP 1.2發生了很大的變化。因為SOAP 1.2 是建立在Infoset上的, SOAP 1.2 Fault本質上是由一個信息條目集合組成。除 了這些變化,SOAP Fault組成部分的名字也做了修改和擴展,以包含更多的描述 信息。SOAP 1.2規定SOAP Fault應該包含一個必須的Code和Reason(原因),一 個可選的Node、Role或Detail(詳細信息)。何時增加這些信息的詳細規定可以 在這裡查看:http://www.w3.org/TR/soap12-part1/#soapfault。通常來說, Code是發生錯誤的標識符,而且也允許使用子code表示更細粒度的信息。SOAP 1.2定義了一些Code,並且允許程序定義自己的Code。Reason便是人工可讀的錯 誤解釋信息。Node表示產生錯誤的消息參與者。Role信息表示的是SOAP錯誤產生 時,消息參與者的角色。Detail是給其它消息參與者准備的錯誤信息。

SOAP 1.1 和1.2 Fault,拋去他們的區別,在他們描述的信息類型上還 是很相似的。兩者都規定了錯誤代碼的標簽,人工可讀的錯誤描述信息,導致 SOAP Fault的消息參與者信息和錯誤的其它信息。為這目的,WCF定義了一個表 示SOAP 1.1和SOAP 1.2 FaultSystem.ServiceModel.Channels.MessageFault類 型。在我們學習如何表示SOAP 1.1 和SOAP 1.2描述的SOAP Fault之前,我們先 來看看MessageFault類型如何概括歸納SOAP Fault的。
MessageFault

The MessageFault type is a way to describe error information in a SOAP-version-agnostic manner. Keeping in mind that WCF has a highly layered architecture, the MessageFault type provides tremendous flexibility when processing SOAP messages and optionally generating exceptions.

MessageFault類型可以描述各種SOAP版本的錯 誤信息。記住WCF擁有更高層的架構,MessageFault類型在處理SOAP消息或者產 生異常的時候提供了巨大的靈活性。

創建一個 MessageFault對象  像 許多WCF裡的別的類型一樣,MessageFault是個定義了幾個工廠方法的抽象類型 。這些工廠方法接受表示SOAP Fault裡存儲信息的參數。此外MessageFault同樣 定義了接受產生SOAP Fault的消息參與者的標識作為參數。值得注意的是, MessageFault定義了一個工廠方法接受一個Message作為參數。這個方法在WCF接 收一個SOAP Fault Message,並需要傳遞這個錯誤信息到別的WCF基礎結構部分 進行處理的時候,非常有用。

System.ServiceModel.FaultCode類型表示 faultcode信息。這個類型定義了幾個工廠方法作為構造函數。所有的構建方法 雲系使用子code。FaultCode類型上的工廠方法,會自動產生發送者和接收者的 錯誤代碼(像SOAP 1.1 和SOAP 1.2定義的一樣)。

System.ServiceModel.FaultReason類型表示faultreason。最簡單的情 況,一個構造函數接受一個String字符串作為參數。String表示人工可讀的錯誤 信息。因為人說的語言不同(Microsoft .NET開發人員也不會說一個語言), FaultReason類型定義了構造函數和方法允許程序嵌入多種版本的String和適當 的基於不同文化的描述信息。

除了那一個MessageFault定義的工廠方法 ,其它的都接受一個FaultCode 和FaultReason類型作為參數。因此,這些類型 必須在MessageFault 創建之前實例化,除了從Message創建MessageFault。幾個 工廠方法也接受Object作為參數,這個表示額外的錯誤信息。對於 Message工廠 方法裡的Object參數,它們必須支持序列化(更多序列化的內容在第9章)。這 個參數的存在帶來一個問題,”我該使用什麼類型作為參數?”因為 System.Exception 是可序列化的,你或許會傳遞一個Exception參數。我強烈建 議你打消這個想法。我更願意自定義一個傳遞錯誤信息給其它消息參與者的類型 。正如我們將會在第9章看到的一樣,這給契約帶來了一個變化。

從 MessageFault創建Message

我們一旦創建了MessageFault,我們可以調 用Message上定義的別的工廠方法來創建一個Message。下面的代碼演示了如何使 用 FaultCode、FaultReason和Object去創建一個MessageFault,也包括如何從 MessageFault創建一個 Message。

static void Main() {
 // create a Receiver Fault Code
 FaultCode faultCode  = FaultCode.CreateReceiverFaultCode("MyFaultCode","urn:MyNS");
  // create a  meaningful FaultReason
 FaultReason faultReason = new  FaultReason("The value must be > 10");

 // create  an object that represents the SOAP Fault detail
  SomeFaultDetail faultDetail = new SomeFaultDetail("Contoso",  "SomeApp");

 // create a MessageFault
  MessageFault messageFault = MessageFault.CreateFault(faultCode,faultReason,faultDetail);

 // Build a  Message from the MessageFault, passing the MessageVersion
 CreateAndShowMessage(messageFault,  MessageVersion.Soap11WSAddressing10);
 CreateAndShowMessage (messageFault, MessageVersion.Soap12WSAddressing10);
}

private static void CreateAndShowMessage(MessageFault  messageFault,
                                          MessageVersion version) {
 //  actually create the Message object w/version info
  Message message = Message.CreateMessage(version,
                               messageFault,
                                            "urn:SomeFaultAction");
 // show the contents of  the Message
 Console.WriteLine("{0}\n", message.ToString ());
}

// a serializable type for storing Fault  detail information
[Serializable]
sealed class  SomeFaultDetail {
 String companyName;
 String  applicationName;
 DateTime? dateOccurred;

 internal  SomeFaultDetail(String companyName, String applicationName) {
    this.companyName = companyName;
     this.applicationName = applicationName;
     //this.dateOccurred = null;
    this.dateOccurred =  DateTime.Now;
 }
}

運行代碼,產生以下結果:

<s:Envelope  xmlns:a="http://www.w3.org/2005/08/addressing"
     xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <a:Action  s:mustUnderstand="1">
      urn:SomeFaultAction
     </a:Action>
 </s:Header>
  <s:Body>
    <s:Fault>
       <faultcode  xmlns:a="urn:MyNS">a:MyFaultCode</faultcode>
       <faultstring xml:lang="en-US">The value must be &gt;  10</faultstring>
      <detail>
         <Program.SomeFaultDetail  xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/MessageFaults">
           <applicationName>SomeApp</applicationName>
           <companyName>Contoso</companyName>
           <dateOccurred>2006-06-14T12:34:44.52325- 04:00</dateOccurred>
         </Program.SomeFaultDetail>
      </detail>
    </s:Fault>
 </s:Body>
</s:Envelope>

<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:SomeFaultAction
     </a:Action>
 </s:Header>
  <s:Body>
    <s:Fault>
       <s:Code>
         <s:Value>s:Receiver</s:Value>
         <s:Subcode>
          <s:Value  xmlns:a="urn:MyNS">a:MyFaultCode</s:Value>
         </s:Subcode>
      </s:Code>
       <s:Reason>
        <s:Text xml:lang="en- US">The value must be &gt; 10</s:Text>
       </s:Reason>
      <s:Detail>
         <Program.SomeFaultDetail  xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/MessageFaults">
           <applicationName>SomeApp</applicationName>
           <companyName>Contoso</companyName>
           <dateOccurred>2006-06-14T12:34:44.52325- 04:00</dateOccurred>
         </Program.SomeFaultDetail>
      </s:Detail>
    </s:Fault>
 </s:Body>
</s:Envelope>

這段代碼展示的最顯著的特性就是 MessageFault如何做到消息版本獨立。第一次調用CreateAndShowMessage傳遞的 參數是MessageFault和 MessageVersion.Soap11WSAddressing10,結果是一個 SOAP 1.1 Fault。第2次調用CreateAndShowMessage傳遞的參數是同一個 MessageFault,但是MessageVersion變為 MessageVersion.Soap12WSAddressing10。結果就是一個SOAP 1.2 Fault。

前面代碼展示了如何從MessageFault創建一個Message。Message定義了 一個接受一個MessageFault參數工廠方法和幾個接受一個FaultCode的工廠方法 。Message的這些工廠方法允許程序創建一個MessageFault或FaultCode標志錯誤 。然後傳遞這個對象給WCF基礎結構裡的其它層去產生一個Message對象。
注釋:這看起來像個小功能,但是確帶來了巨大好處。作用上,MessageFault 類型的MessageVersion版本兼容能力允許在WCF基礎結構的另外部分來決定SOAP 消息版本。換句話說,WCF基礎結構裡只有一層為了傳輸需要知道SOAP消息版本 ,因此創建了一個熱拔插和可擴展的框架。

老徐備注

1.SOAP Fault 元素

來自 SOAP 消息的錯誤消息被攜帶於 Fault 元素內部。

如果已提供了 Fault 元素,則它必須是 Body 元素的子元素。在一條 SOAP 消息中,Fault 元素只能出現一次。

SOAP 的 Fault 元素用於下列 子元素:

子元素 描述 <faultcode> 供識別故障的代碼 <faultstring> 可供人閱讀的有關故障的說 明 <faultactor> 有關是誰引發故障的信息 <detail> 存留涉及 Body 元素的應用程序 專用錯誤信息

2.SOAP Fault Codes

在下面 定義的 faultcode 值必須用於描述故障時的 faultcode 元素中:

錯誤 描述 VersionMismatch SOAP Envelope 元素的無效命名 空間被發現 MustUnderstand Header 元素的一個直 接子元素(帶有設置為 "1" 的 mustUnderstand 屬性)無法被理解。 Client 消息被不正確地構成,或包含了不正確的 信息。 Server 服務器有問題,因此無法處理進行 下去。

參考: http://www.w3school.com.cn/soap/soap_fault.asp

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