2013-06-13 10 views
6

Ich versuche, weitere Informationen zu einem SOAP-Fehler in einer Open-Source-Clientanwendung hinzuzufügen. Der Client ist so eingerichtet, dass er "HandleFault" aufruft, wenn ein SOAP-Fehler auftritt. Der Griff Fehler Methode ist unten dargestellt:Behandeln der WCF-Fehlerausnahme

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) 
     ); 
    } 

Hier ist ein Teil der SOAP-Fehler, die als „Nachricht“ wird übergeben, wenn ich versuche und eine Telefonnummer zu einem ungültigen Format von der Client etwas wie ändern.

<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> 

Jedes Mal, wenn die Störung aufgetreten ist, kehrt der Client nur zurück „Die Anforderungsnachricht Fehler enthält, der die Anforderung verhindern Verarbeitung.“ Ich möchte die „AttributeRepresentationFailure“ Knoten und Kind einschließen Knoten vor dem erneuten Auslösen der Ausnahme im Client.

Die Art, wie ich es verstehe, ist, dass ich eine Fehlerklasse definieren muss, die die zu deserialisierenden Details enthält, so dass der Aufruf von "CreateFault" ein zurückgeben kann. Ich habe http://msdn.microsoft.com/en-us/library/ms733841.aspx gelesen, aber ich verstehe einfach nicht genau, wie man die Klasse definiert, damit der Client weiß, welche Art von Fehler ausgelöst wird.

UPDATE

Im Griff Fehler Methode Client-Seite hinzugefügt I

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

Der Fehler immer unter dem Basisfehlerklasse "otherFault" gefangen wird. Meine InvalidRepresentation Klasse ist definiert als unter

[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() { 

    } 
} 

Antwort

1

ich Mathe Beispiel aus dem Artikel bin mit bezeichnen Sie. Erstellen Sie die Fehlerklasse:

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

Dekorieren Sie Ihre Methode mit OperationContract, z.

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

Erstellen Sie Ihr MathFault-Objekt mit sinnvollen Daten. Wickeln Sie es ein und werfen Sie es:

throw new FaultException<MathFault>(yourFault); 

Hoffe, dass dies hilft.

+0

danke! Ich denke, ich bin auf dem richtigen Weg, aber wenn ich meine Fehlerklasse definiere, wie muss diese Klasse aussehen, um den Fehler in dem Beispiel, das ich oben gesendet habe, richtig zu behandeln? Außerdem, wie in der Client-Code ich bestimmen, welche Fehler ausgelöst wurde, nehme ich an, dass im 'System.ServiceModel.FaultException.CreateFault' Code behandelt wird? –

3

Um Fredriks Antwort hinzuzufügen, kann Ihre Fault-Klasse alles sein, was Sie benötigen, um die Details Ihres benutzerdefinierten Fehlers dem Client mitzuteilen. Es muss nicht von einer anderen Klasse erben oder eine Schnittstelle implementieren. Es muss nur mit dem DataContract-Attribut markiert werden.

Was es auf der Clientseite zu kontrollieren:

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

Danke @Jason, aber mein Fehler wird nie als eine ungültige Darstellung gefangen. Es wird immer als generische FaultException abgefangen. Ich habe den DataContract in meiner InvalidRepresentation-Klasse definiert. Ich verstehe nicht, wie es weiß, welche Art von Fehler geworfen wird ?? –

+0

Auf der Service-Seite, werfen Sie den Fehler in der Art und Weise, die Fredrik unten beschrieben? 'Werfen neue FaultException (yourFault);' – Jason

2

war ich endlich in der Lage, eine Resolution zu diesem zu finden, vielen Dank an alle, die geholfen haben! Dies ist nicht die beste Lösung und muss aufgeräumt werden, aber es funktioniert solange, bis ich mehr über WCF- und SOAP-Fehler erfahren habe. Außerdem habe ich keinen Zugriff auf den Service-Code, nur den Client-Code. Der Client-Code wird als Powershell-Modul ausgeführt.

InvalidRepresentationFault Klasse

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; 
} 

}

Kunde HandleFault-Code

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; 
     } 
    } 

Nun, wenn der Dienst eine SOAP-Fehler wirft es in die "RepresentationFailures" Klasse deserialisiert wird, die ich anpassen kann, bevor ich zurückwerfe vorgelagert (in diesem Fall zur Powershell)

+0

gute Muster-Mapper ** FaultException ** bis ** Exception **? – Kiquenet

+0

Keine Exception werfen. Erstellen Sie Ihre eigene benutzerdefinierte Ausnahme und übergeben Sie, was Sie benötigen. – nashwan