2008-09-15 1 views
9

FaultExceptionとFaultException <T>を使用して、私たちのアプリケーションで最良の使用パターンを調べることを試しています。 SOAP 1.1とSOAP 1.2クライアントを含むWCF以外のサービスコンシューマ/クライアントと同様に、WCFをサポートする必要があります。.NET WCFのフォールトが不正なSOAP 1.1フォルトコード値を生成しています

FYI: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クラスには、以下を参照してくださいすることができますよう、文字列「メッセージ」プロパティが含まれているだけの簡単なテストクラスです。

応答をwsHttpBinding使用している:これは、SOAP 1.2仕様に応じて右に見える

<?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&lt;FaultDetails&gt;.</Message> 
    </FaultDetails> 
</Detail> 

。メイン/ルート "Code"は "Sender"で、 "MySubFaultCode"の "Subcode"を持っています。サービスコンシューマ/クライアントが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&lt;FaultDetails&gt;.</Message> 
    </FaultDetails> 
    </detail> 
</s:Fault> 

これは右見ていません。 SOAP 1.1の仕様を見ると、FaultCode.CreateSenderFaultCode(新しいFaultCode( "MySubFaultCode"))を使用すると、 "faultcode"の値が "s:Client.MySubFaultCode"になることを期待していました。また、WCFクライアントの構造が正しくありません。 faultException.Code.Nameは「Sender」ではなく「MySubFaultCode」であり、faultException.Code.SubCode.Nameが「MySubFaultCode」ではなく、faultException.Code.SubCodeがnullです。また、faultException.Code.IsSenderFaultはfalseです。

同様の問題FaultCode.CreateReceiverFaultCode(新規のFaultCode( "MySubFaultCode"))を使用する場合:SOAP 1.2

  • ために期待されるよう

    • 作品を生成Server.MySubFaultCode:代わりに「Sの「S MySubFaultCodeを」 faultException.Code.IsReceiverFaultはSOAP 1.1の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

    マイクロソフト接続をバグ: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で?

  • 答えて

    8

    これが私の現在の回避策です:

    /// <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では機能します。マイクロソフトから

    7

    応答:http://msdn.microsoft.com/en-us/library/ms789039.aspxで説明したように

    、カスタムの故障コードのためのSOAP 1.1仕様で概説した2つの方法があります

    (1)「ドット」表記を使用して、あなたが

    を説明するように

    (2)完全に新しいフォールトコードを定義する

    残念ながら、「ドット」表記は避けてください.WS-I Basic Profile仕様では使用しないでください。基本的に、これは、Soap 1.1を使用しているときに、Soap 1.2フォールトサブコードの実際の同等物が存在しないことを意味します。

    したがって、フォルトを生成するときは、バインディングで定義されたMessageVersionを認識し、それに応じてフォルトコードを生成する必要があります。

    "送信者"と "受信者"はSoap 1.1のvaildフォールトコードではないため、フォールトサブコードと同等のものは存在しませんので、CreateSenderFaultCodeメソッドとCreateReceiverFaultCodeメソッドを使用しないでください。

    代わりに、自分の名前空間と名前使用して、独自ののfaultcodeを定義する必要があります:

    のFaultCode customFaultCode =新しいのFaultCode(ローカル名、faultNamespaceを)。

    関連する問題