Frage

Ich experimentiere die FaultException und FaultException mit der Verwendung der besten Nutzungsmuster in unseren Anwendungen zu bestimmen. Wir müssen WCF als auch Nicht-WCF-Dienst Verbraucher / Kunden unterstützen, einschließlich SOAP 1.1 und SOAP 1.2-Clients.

Zur Info: mit FaultExceptions mit wsHttpBinding Ergebnissen in SOAP 1.2 Semantik während FaultExceptions mit Basichttpbinding Ergebnissen in SOAP 1.1 Semantik.

Ich bin mit dem folgenden Code einen FaultException 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 die Antwort mit WSHttpBinding 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>

Das sieht richtig nach der SOAP 1.2-Spezifikationen. Der Haupt / root „Code“ ist „Sender“, die eine „Subcode“ von „MySubFaultCode“ hat. Wenn der Service-Consumer / Client verwendet WCF die FaultException auf der Client-Seite ahmt auch die gleiche Struktur, mit dem faultException.Code.Name sein „Sender“ und faultException.Code.SubCode.Name seinen „MySubFaultCode“.

Wenn die Antwort mit Basichttpbinding 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. Mit Blick auf den SOAP 1.1-Spezifikationen, erwarte ich die „faultcode“ um zu sehen, einen Wert zu haben, „s: Client.MySubFaultCode“ wenn ich FaultCode.CreateSenderFaultCode (neu FaultCode ( „MySubFaultCode“)). Auch ein WCF-Client erhält eine falsche Struktur. Der faultException.Code.Name ist „MySubFaultCode“ anstelle dem Sein „Sender“ und der faultException.Code.SubCode ist null statt faultException.Code.SubCode.Name „MySubFaultCode“ zu sein. Auch der faultException.Code.IsSenderFault falsch ist.

Ein ähnliches Problem, wenn FaultCode.CreateReceiverFaultCode (neu FaultCode ( "MySubFaultCode")) mit:

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

Dieser Punkt wurde auch von jemand anderem auf http: // forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1 im Jahr 2006 und niemand hat es beantwortet. Ich finde es sehr schwer zu glauben, dass niemand in dieser ausgeführt wird, noch nicht.

Hier ist jemand anderes ein ähnliches Problem mit: 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 sollen:

War es hilfreich?

Lösung

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 kompatibel faultcode Werte erstellen, aber es bricht SOAP 1.2.

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

Andere Tipps

Antwort von Microsoft:

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

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

(2) definiert völlig neuen Fehlercodes

Leider sollte der „Punkt“ Notation vermieden werden, da es die Verwendung ist in der WS-I Basic Profile Spezifikation abgeraten. Im Wesentlichen bedeutet dies, dass es keine wirkliche Äquivalent des Fehler SubCode Soap 1.2 ist bei der Verwendung von Seife 1.1.

Also, wenn Fehler zu erzeugen, werden Sie bewusst die Message in der Bindung definiert sein müssen, und erzeugen faultcodes entsprechend.

Da „Sender“ und „Empfänger“ ist nicht vaild Fehlercodes für Soap 1.1, und es gibt kein wirkliches Äquivalent eines Fehler Subcode, sollten Sie nicht die CreateSenderFaultCode und CreateReceiverFaultCode Methoden verwenden, wenn benutzerdefinierten Fehlercodes für Soap 1.1 zu erzeugen.

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

FaultCode customFaultCode = new FaultCode (local, faultNamespace);

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top