2008-09-15 17 views
9

Ich experimentiere mit der Verwendung von FaultException und FaultException <T>, um das beste Nutzungsmuster in unseren Anwendungen zu ermitteln. Wir müssen sowohl WCF- als auch Nicht-WCF-Service-Consumer/Clients unterstützen, einschließlich SOAP 1.1- und SOAP 1.2-Clients..NET WCF-Fehler, die falsche SOAP 1.1-Fehlercodewerte generieren

FYI: die Verwendung von FaultExceptions mit wsHttpBinding führt zu SOAP 1.2-Semantik, während die Verwendung von FaultExceptions mit basicHttpBinding zu SOAP 1.1-Semantik führt.

ich den folgenden Code verwenden < FaultDetails ein FaultException > zu werfen:

throw new FaultException<FaultDetails>(
     new FaultDetails("Throwing FaultException<FaultDetails>."), 
     new FaultReason("Testing fault exceptions."), 
     FaultCode.CreateSenderFaultCode(new FaultCode("MySubFaultCode")) 
    ); 

Die FaultDetails Klasse ist nur eine einfache Test-Klasse, die eine Zeichenfolge „Nachricht“ Eigenschaft enthält, wie Sie unten sehen können.

Wenn WSHttpBinding die Antwort unter Verwendung ist:

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

Diese 1.2-Spezifikationen nach dem SOAP richtig aussieht. Der Haupt/root "Code" ist "Sender", der einen "Subcode" von "MySubFaultCode" hat. Wenn der Service-Consumer/Client WCF verwendet, simuliert die FaultException auf der Clientseite auch die gleiche Struktur, wobei faultException.Code.Name "Sender" und faultException.Code.SubCode.Name "MySubFaultCode" ist.

Wenn Basichttpbinding die Antwort unter Verwendung ist:

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

Das sieht nicht richtig aus. Bei der Betrachtung der SOAP 1.1-Spezifikationen erwartete ich, dass der "Fehlercode" den Wert "s: Client.MySubFaultCode" hat, wenn ich FaultCode.CreateSenderFaultCode (neuer FaultCode ("MySubFaultCode")) verwende. Auch ein WCF-Client erhält eine falsche Struktur. Der faultException.Code.Name ist "MySubFaultCode" anstatt "Absender" zu sein, und der faultException.Code.SubCode ist null anstelle von faultException.Code.SubCode.Name ist "MySubFaultCode". Außerdem ist faultException.Code.IsSenderFault falsch.

ähnliches Problem bei der Verwendung von FaultCode.CreateReceiverFaultCode (neu FaultCode ("MySubFaultCode")):

  • Werke wie für SOAP 1.2
  • erwartet
  • erzeugt „s: MySubFaultCode“ statt „s: Server.MySubFaultCode “und die faultException.Code.IsReceiverFault ist falsch für SOAP 1,1

Dieses Produkt wird auch von jemand anderem auf http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1 im Jahr 2006 und niemand hat es beantwortet gebucht wurde. Ich finde es sehr schwer zu glauben, dass noch niemand darauf gestoßen ist.

Hier ist jemand anderes ein ähnliches Problem: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3883110&SiteID=1&mode=1

Microsoft Connect Fehler: https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=367963

Beschreibung, wie Störungen funktionieren sollte: http://blogs.msdn.com/drnick/archive/2006/12/19/creating-faults-part-3.aspx

Bin ich das wirklich ein Bug etwas falsch oder ist zu tun in WCF?

Antwort

8

Dies ist meine aktuelle Problemumgehung:

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

Leider sehe ich keine Möglichkeit Subcodes zu verwenden, ohne zu brechen entweder SOAP 1.1 oder 1.2-Clients.

Wenn Sie die Code.SubCode-Syntax verwenden, können Sie SOAP 1.1-kompatible Faultcode-Werte erstellen, es bricht jedoch SOAP 1.2.

Wenn Sie die richtige Subcode-Unterstützung in .NET verwenden (entweder über die statischen FaultCode-Methoden oder eine der Überladungen), bricht es SOAP 1.1, funktioniert aber in SOAP 1.2.

7

Antwort von Microsoft:

Wie in http://msdn.microsoft.com/en-us/library/ms789039.aspx diskutiert, gibt es zwei in der Soap-1.1-Spezifikation beschriebene Methoden für benutzerdefinierten Fehlercodes:

(1) Mit der "Punkt" Notation, wie Sie

beschreiben

(2) Definieren völlig neuer Fehlercodes

Leider sollte die "Punkt" -Notation vermieden werden, da ihre Verwendung in der WS-I-Basisprofilspezifikation nicht empfohlen wird. Im Wesentlichen bedeutet dies, dass es kein echtes Äquivalent des Soap 1.2-Fehler-SubCodes gibt, wenn Soap 1.1 verwendet wird.

Wenn Sie also Fehler erzeugen, müssen Sie sich der in der Bindung definierten MessageVersion bewusst sein und entsprechende Fehlercodes generieren.

Da "Sender" und "Empfänger" keine gültigen Fehlercodes für Soap 1.1 sind und kein wirkliches Äquivalent eines Fehler-Subcodes vorhanden ist, sollten Sie beim Generieren benutzerdefinierter Fehlercodes für Soap 1.1 nicht die CreateSenderFaultCode- und CreateReceiverFaultCode-Methoden verwenden .

Stattdessen müssen Sie Ihre eigene faultcode definieren, einen eigenen Namensraum und den Namen mit:

FaultCode customFaultCode = new FaultCode (local, faultNamespace);

Verwandte Themen