2013-06-13 12 views
6

オープンソースのクライアントアプリケーションでSOAP障害に関する詳細を追加しようとしています。クライアントは、SOAPフォールトが発生するたびに「HandleFault」を呼び出すように設定されています。ハンドルフォルト方法を以下に示します。WCFフォールト例外を処理する方法

ここ
public static void HandleFault(Message message) { 
     MessageFault fault = MessageFault.CreateFault(message, Int32.MaxValue); 
     throw System.ServiceModel.FaultException.CreateFault(fault, 
      typeof(PermissionDeniedFault), 
      typeof(EndpointUnavailable), 
      typeof(InvalidRepresentation), 
      typeof(UnwillingToPerformFault), 
      typeof(CannotProcessFilter), 
      typeof(AnonymousInteractionRequiredFault) 
     ); 
    } 

は私がしようとすると、クライアントからの不正な形式に変更のように電話番号を何かをする時に「メッセージ」として渡されるSOAPフォルトの部分です。

<s:Body u:Id="_2"> 
<Fault xmlns="http://www.w3.org/2003/05/soap-envelope"> 
    <Code> 
    <Value>Sender</Value> 
    <Subcode> 
     <Value xmlns:a="http://schemas.xmlsoap.org/ws/2004/09/transfer">a:InvalidRepresentation</Value> 
    </Subcode> 
    </Code> 
    <Reason> 
    <Text xml:lang="en-US">The request message contains errors that prevent processing the request.</Text> 
    </Reason> 
    <Detail> 
    <RepresentationFailures xmlns="http://schemas.microsoft.com/2006/11/ResourceManagement" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
     <AttributeRepresentationFailure> 
     <AttributeType>OfficePhone</AttributeType> 
     <AttributeValue>(123)456-7890</AttributeValue> 
     <AttributeFailureCode>ValueViolatesRegularExpression</AttributeFailureCode> 
     <AdditionalTextDetails>The specified attribute value does not satisfy the regular expression.</AdditionalTextDetails> 
     </AttributeRepresentationFailure> 
     <CorrelationId>11042dda-3ce9-4563-b59e-d1c1355819a4</CorrelationId> 
    </RepresentationFailures> 
    </Detail> 
</Fault> 

その障害が発生したときはいつでも、クライアントは戻っ「要求メッセージは、要求を処理妨げるエラーが含まれています。」、私は「AttributeRepresentationFailure」ノードと子を含めたいですノードを削除してから、クライアントに例外を再スローします。

私が理解しているのは、 "CreateFault"の呼び出しがaを返すように、それらの詳細を含むFaultクラスを定義する必要があることです。 http://msdn.microsoft.com/en-us/library/ms733841.aspxを読んだことがありますが、クラスを定義する方法を正確に理解できないため、クライアントはどのタイプの障害がスローされるかを知ることができます。クライアントサイドハンドル断層法では

UPDATE

私は障害が常にベースの障害クラスの下に巻き込まれる "otherFault"

try 
     { 
      throw faultexcept; 
     } 
     catch (System.ServiceModel.FaultException<InvalidRepresentation> invalidRepresentationFault) 
     { 
      throw invalidRepresentationFault; 
     } 
     catch (System.ServiceModel.FaultException otherFault) 
     { 
      throw otherFault; 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 

を追加しました。 マイInvalidRepresentationクラスは、私はあなたが言及記事から数学の例を使用してい

[DataContract(Namespace = Constants.Rm.Namespace)] 
public class InvalidRepresentation 
{ 
    private string _attributeType; 
    private string _attributeValue; 
    private string _attributeFailureCode; 
    private string _additionalTextDetails; 

    [DataMember] 
    public string AttributeType 
    { 
     get { return _attributeType; } 
     set { _attributeType = value; } 
    } 

    [DataMember] 
    public string AttributeValue 
    { 
     get { return _attributeValue; } 
     set { _attributeValue = value; } 
    } 

    [DataMember] 
    public string AttributeFailureCode 
    { 
     get { return _attributeFailureCode; } 
     set { _attributeFailureCode = value; } 
    } 

    [DataMember] 
    public string AdditionalTextDetails 
    { 
     get { return _additionalTextDetails; } 
     set { _additionalTextDetails = value; } 
    } 


    public InvalidRepresentation() { 

    } 
} 

答えて

1

以下のように定義されます。エラークラスを作成します。

[DataContract(Namespace="http://Microsoft.ServiceModel.Samples")] 
public class MathFault 
{  
... 
} 

OperationContractでメソッドをデコレートします。

[OperationContract] 
[FaultContract(typeof(MathFault))] 
int Divide(int n1, int n2); 

わかりやすいデータでMathFaultオブジェクトを作成します。ラップして投げてください:

throw new FaultException<MathFault>(yourFault); 

希望します。

+0

ありがとう!私は正しい軌道に乗っていると思うが、私のFaultクラスを定義するとき、上記の例のフォールトを適切に処理するためには、そのクラスはどのように見える必要がありますか?また、クライアントコードでどのようにFaultがスローされたのかを判断するには、 'System.ServiceModel.FaultException.CreateFault'コードで処理されていると仮定していますか? –

3

Fredrikの答えに追加するには、カスタムエラーの詳細をクライアントに伝えるために必要なものをFaultクラスにすることができます。他のクラスから継承する必要はなく、インタフェースを実装する必要もありません。これは、DataContract属性でマークする必要があります。クライアント側でそれをキャッチするためとして

try 
{ 
    ... 
} 
catch (FaultException<MathFault> mathFault) 
{ 
    // handle a math fault 
} 
catch (FaultException<OtherCustomFault> otherFault) 
{ 
    // handle another type of custom fault 
} 
catch (Exception ex) 
{ 
    // regular exception handling 
} 
+0

ありがとう@ジェイソン、私の障害は決してInvalidRepresentationとして捕らえられることはありません。これは、一般的なFaultExceptionとして常に捕らえられます。私はInvalidRepresentationクラスで定義されたDataContractを持っています。どのようなタイプの障害が投げられているのか、私はどのように知っているのか分かりませんか? –

+0

サービス側では、Fredrikが以下に説明したようにフォールトを投げていますか? '新しいFaultExceptionをスローする(yourFault); ' – Jason

2

私は最終的に、助けみんなのおかげでこれに対する解決を見つけることができました!これは最善の解決策ではなく、クリーンアップする必要がありますが、WCFとSOAPフォルトについてもっと学ぶまでは動作します。また、私はサービスコード、クライアントコードにアクセスする必要はありません。クライアントコードは、PowerShellモジュールとして実行されています。

InvalidRepresentationFaultクラス

using System.Runtime.Serialization; 
namespace Client.Faults { 
    public class InvalidRepresentationFault 
    { 
     public InvalidRepresentationFault() {} 
    } 
    [DataContract(Namespace = Constants.Rm.Namespace)] 
    public class RepresentationFailures 
    { 
     [DataMember()] 
     public FailureDetail AttributeRepresentationFailure; 

    [DataContract(Namespace = Constants.Rm.Namespace)] 
    public class FailureDetail 
    { 
     [DataMember(Order = 1)] 
     public string AttributeType; 

     [DataMember(Order = 2)] 
     public string AttributeValue; 

     [DataMember(Order = 3)] 
     public string AttributeFailureCode; 

     [DataMember(Order = 4)] 
     public string AdditionalTextDetails; 
    } 

    [DataMember] 
    public string CorrelationId; 
} 

}

クライアントのhandleFaultコード

public static void HandleFault(Message message) { 
     MessageFault fault = MessageFault.CreateFault(message, Int32.MaxValue); 

     //Let the fault exception choose the best fault to handle? 
     System.ServiceModel.FaultException faultexcept = System.ServiceModel.FaultException.CreateFault(fault, 
      typeof(PermissionDeniedFault), 
      typeof(AuthenticationRequiredFault), 
      typeof(AuthorizationRequiredFault), 
      typeof(EndpointUnavailable), 
      typeof(FragmentDialectNotSupported), 
      typeof(InvalidRepresentationFault), 
      typeof(UnwillingToPerformFault), 
      typeof(CannotProcessFilter), 
      typeof(FilterDialectRequestedUnavailable), 
      typeof(UnsupportedExpiration), 
      typeof(AnonymousInteractionRequiredFault), 
      typeof(RepresentationFailures) 
     ); 

     try 
     { 
      throw faultexcept; 
     } 
     catch (System.ServiceModel.FaultException<RepresentationFailures> invalidRepresentationFault) 
     { 
      throw new Exception(
       String.Format(
        "{0}\r\nfor Attribute \"{1}\" with Value \"{2}\"", 
         invalidRepresentationFault.Detail.AttributeRepresentationFailure.AdditionalTextDetails, 
         invalidRepresentationFault.Detail.AttributeRepresentationFailure.AttributeType, 
         invalidRepresentationFault.Detail.AttributeRepresentationFailure.AttributeValue 
        ), 
       invalidRepresentationFault 
      ); 
     } 
     catch (System.ServiceModel.FaultException otherFault) 
     { 
      throw otherFault; 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

サービスは、SOAPフォールトをスローしたときに今では "RepresentationFailures" クラスにデシリアライズされます、私はそれを再スローする前にカスタマイズすることができます上流(この場合はpowershell)

+0

良いパターンマッパー** FaultException ** to ** Exception **? – Kiquenet

+0

例外をスローしないでください。独自のカスタム例外を作成し、必要なものを渡します。 – nashwan

関連する問題