2013-06-13 16 views
6

Próbuję dodać więcej informacji dotyczących błędu SOAP w aplikacji klienckiej Open Source. Klient jest skonfigurowany do wywoływania "HandleFault" za każdym razem, gdy napotka jakiś błąd SOAP. Metoda Uchwyt błędu przedstawiono poniżej:Jak radzić sobie z wyjątkami dotyczącymi wylewów 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) 
     ); 
    } 

Oto część winy SOAP, która jest przekazywana jako „wiadomości”, gdy próbuję coś zrobić i jak zmienić numer telefonu, na nieprawidłowym formacie od klienta.

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

Ilekroć że usterka zostanie napotkany, klient zwraca tylko z powrotem „Przesłanie wniosek zawiera błędy, które uniemożliwiają przetwarzania żądania.” Chciałbym obejmują „AttributeRepresentationFailure” węzeł i dziecko węzły przed ponownym wyrzuceniem wyjątku w kliencie.

Sposób, jaki rozumiem, polega na tym, że muszę zdefiniować klasę błędów, która zawiera szczegóły, które mają zostać zdealizowane, aby wywołanie funkcji "CreateFault" mogło zwrócić wartość a. Przeczytałem przez http://msdn.microsoft.com/en-us/library/ms733841.aspx, ale po prostu nie rozumiem dokładnie, jak zdefiniować klasę, aby klient wiedział, jaki typ błędu jest zgłaszany.

UPDATE

po stronie klienta metodą błędu uchwyt dodałem

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

Błąd jest zawsze złowionych pod klasę błędu baza "otherFault". Moja klasa InvalidRepresentation jest zdefiniowany jako poniżej

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

    } 
} 

Odpowiedz

1

używam przykład matematyki z artykułu Państwo, o którym mowa. Utwórz klasę błędu:

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

Udekoruj swoją metodę za pomocą OperationContract, np.

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

Utwórz swój obiekt MathFault za pomocą rozsądnych danych. Zawiń go i wrzuć:

throw new FaultException<MathFault>(yourFault); 

Mam nadzieję, że to pomoże.

+0

dzięki! Myślę, że jestem na dobrej drodze, ale kiedy definiuję moją klasę błędów, co ta klasa musi wyglądać, aby prawidłowo obsłużyć błąd w przykładzie, który wysłałem powyżej? Ponadto, w jaki sposób w kodzie klienta mogę określić, jaki błąd został zgłoszony, zakładam, że to zostało zajęte w kodzie "System.ServiceModel.FaultException.CreateFault"? –

3

Aby dodać do odpowiedzi Fredrika, Twoja klasa błędów może być tym, czego potrzebujesz, aby przekazać klientowi szczegóły niestandardowego błędu. Nie musi dziedziczyć z innej klasy ani implementować interfejsu. To musi być zaznaczone atrybutem DataContract.

chodzi o łapanie go po stronie klienta:

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

Dzięki @Jason, ale moja wina nigdy nie została złapana jako InvalidRepresentation. Jest zawsze złapany jako ogólny wyjątek FaultException. Mam DataContract zdefiniowany w mojej klasie InvalidRepresentation. Nie rozumiem, jak wie, jaki typ usterki jest rzucany? –

+0

Po stronie usługi, rzucasz błąd w sposób opisany przez Fredrika poniżej? 'Throw new FaultException (yourFault);' – Jason

2

I w końcu udało się znaleźć rozwiązanie dla tego, dzięki wszystkim, którzy pomogli! To nie jest najlepsze rozwiązanie i należy je wyczyścić, ale działa dopóki nie dowiem się więcej o błędach WCF i SOAP. Ponadto nie mam dostępu do kodu usługi, tylko kod klienta. Kod klienta jest uruchamiany jako moduł powershell.

InvalidRepresentationFault Klasa

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

}

Client HandleFault Kod

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

Teraz, gdy usługa rzuca SOAP Fault robi rozszeregować do klasy "RepresentationFailures" które mogę spersonalizować przed ponownym wyrzuceniem w górę (w tym przypadku PowerShell)

+0

dobry schemat odwzorowania ** FaultException ** to ** Exception **? – Kiquenet

+0

Nie wyrzucaj wyjątku. Stwórz własny niestandardowy wyjątek i podaj w nim to, czego potrzebujesz. – nashwan

Powiązane problemy