.NET WCF 錯誤生成不正確的 SOAP 1.1 錯誤程式碼值
我正在嘗試使用 FaultException 和 FaultException<T> 來確定我們應用程序中的最佳使用模式。我們需要支持 WCF 以及非 WCF 服務消費者/客戶端,包括 SOAP 1.1 和 SOAP 1.2 客戶端。
僅供參考:使用帶有 wsHttpBinding 的 FaultExceptions 會產生 SOAP 1.2 語義,而使用帶有 basicHttpBinding 的 FaultExceptions 會產生 SOAP 1.1 語義。
我正在使用以下程式碼拋出 FaultException<FaultDetails>:
throw new FaultException<FaultDetails>( new FaultDetails("Throwing FaultException<FaultDetails>."), new FaultReason("Testing fault exceptions."), FaultCode.CreateSenderFaultCode(new FaultCode("MySubFaultCode")) );FaultDetails 類只是一個簡單的測試類,它包含一個字元串“Message”屬性,如下所示。
使用 wsHttpBinding 時,響應為:
<?xml version="1.0" encoding="utf-16"?> <Fault xmlns="http://www.w3.org/2003/05/soap-envelope"> <Code> <Value>Sender</Value> <Subcode> <Value>MySubFaultCode</Value> </Subcode> </Code> <Reason> <Text xml:lang="en-US">Testing fault exceptions.</Text> </Reason> <Detail> <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Message>Throwing FaultException<FaultDetails>.</Message> </FaultDetails> </Detail>根據 SOAP 1.2 規範,這看起來是正確的。主/根“程式碼”是“發件人”,其“子程式碼”為“MySubFaultCode”。如果服務使用者/客戶端使用 WCF,客戶端上的 FaultException 也模仿相同的結構,faultException.Code.Name 為“Sender”,faultException.Code.SubCode.Name 為“MySubFaultCode”。
使用 basicHttpBinding 時,響應為:
<?xml version="1.0" encoding="utf-16"?> <s:Fault xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <faultcode>s:MySubFaultCode</faultcode> <faultstring xml:lang="en-US">Testing fault exceptions.</faultstring> <detail> <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Message>Throwing FaultException<FaultDetails>.</Message> </FaultDetails> </detail> </s:Fault>這看起來不對。查看 SOAP 1.1 規範,當我使用 FaultCode.CreateSenderFaultCode(new FaultCode(“MySubFaultCode”)) 時,我希望看到“faultcode”的值為“s:Client.MySubFaultCode”。此外,WCF 客戶端的結構不正確。faultException.Code.Name 是“MySubFaultCode”而不是“Sender”,faultException.Code.SubCode 是 null 而不是 faultException.Code.SubCode.Name 是“MySubFaultCode”。此外,faultException.Code.IsSenderFault 為假。
使用 FaultCode.CreateReceiverFaultCode(new FaultCode(“MySubFaultCode”)) 時的類似問題:
- 按預期工作於 SOAP 1.2
- 生成“s:MySubFaultCode”而不是“s:Server.MySubFaultCode”,並且 SOAP 1.1 的 faultException.Code.IsReceiverFault 為 false
這個項目也是2006年別人在http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1上發布的,沒有人回答。我很難相信還沒有人遇到過這種情況。
這是其他人遇到類似問題:http ://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3883110&SiteID=1&mode=1
Microsoft Connect 錯誤:https ://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=367963
故障應該如何工作的描述:http: //blogs.msdn.com/drnick/archive/2006/12/19/creating-faults-part-3.aspx
我做錯了什麼還是這真的是 WCF 中的一個錯誤?
這是我目前的解決方法:
/// <summary> /// Replacement for the static methods on FaultCode to generate Sender and Receiver fault codes due /// to what seems like bugs in the implementation for basicHttpBinding (SOAP 1.1). wsHttpBinding /// (SOAP 1.2) seems to work just fine. /// /// The subCode parameter for FaultCode.CreateReceiverFaultCode and FaultCode.CreateSenderFaultCode /// seem to take over the main 'faultcode' value in the SOAP 1.1 response, whereas in SOAP 1.2 the /// subCode is correctly put under the 'Code->SubCode->Value' value in the XML response. /// /// This workaround is to create the FaultCode with Sender/Receiver (SOAP 1.2 terms, but gets /// translated by WCF depending on the binding) and an agnostic namespace found by using reflector /// on the FaultCode class. When that NS is passed in WCF seems to be able to generate the proper /// response with SOAP 1.1 (Client/Server) and SOAP 1.2 (Sender/Receiver) fault codes automatically. /// /// This means that it is not possible to create a FaultCode that works in both bindings with /// subcodes. /// </summary> /// <remarks> /// See http://stackoverflow.com/questions/65008/net-wcf-faults-generating-incorrect-soap-11-faultcode-values /// for more details. /// </remarks> public static class FaultCodeFactory { private const string _ns = "http://schemas.microsoft.com/ws/2005/05/envelope/none"; /// <summary> /// Creates a sender fault code. /// </summary> /// <returns>A FaultCode object.</returns> /// <remarks>Does not support subcodes due to a WCF bug.</remarks> public static FaultCode CreateSenderFaultCode() { return new FaultCode("Sender", _ns); } /// <summary> /// Creates a receiver fault code. /// </summary> /// <returns>A FaultCode object.</returns> /// <remarks>Does not support subcodes due to a WCF bug.</remarks> public static FaultCode CreateReceiverFaultCode() { return new FaultCode("Receiver", _ns); } }遺憾的是,我看不到在不破壞 SOAP 1.1 或 1.2 客戶端的情況下使用子程式碼的方法。
如果您使用 Code.SubCode 語法,您可以創建與 SOAP 1.1 兼容的錯誤程式碼值,但它會破壞 SOAP 1.2。
如果您在 .NET 中使用適當的子程式碼支持(通過靜態 FaultCode 方法或其中一種重載),它會破壞 SOAP 1.1,但在 SOAP 1.2 中有效。