《WCF技术内幕》翻译25:第2部分_第5章_消息:创建一个消息(下)之MessageFault
生活随笔
收集整理的這篇文章主要介紹了
《WCF技术内幕》翻译25:第2部分_第5章_消息:创建一个消息(下)之MessageFault
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Message和SOAP Fault老徐備注1
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 FaultMessage,并需要傳遞這個錯誤信息到別的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 > 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 > 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 元素的應用程序專用錯誤信息 |
| 錯誤 | 描述 |
| VersionMismatch | SOAP Envelope 元素的無效命名空間被發現 |
| MustUnderstand | Header 元素的一個直接子元素(帶有設置為 "1" 的 mustUnderstand 屬性)無法被理解。 |
| Client | 消息被不正確地構成,或包含了不正確的信息。 |
| Server | 服務器有問題,因此無法處理進行下去。 |
總結
以上是生活随笔為你收集整理的《WCF技术内幕》翻译25:第2部分_第5章_消息:创建一个消息(下)之MessageFault的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 2042:不容易系列之二
- 下一篇: lammps教程:NEMD方法计算热导率