Question

J'essaie d'utiliser les exceptions FaultException et FaultException < T > pour déterminer le meilleur modèle d'utilisation dans nos applications. Nous devons prendre en charge les clients / clients de services non-WCF, ainsi que les clients SOAP 1.1 et SOAP 1.2.

FYI: utiliser FaultExceptions avec wsHttpBinding a pour résultat la sémantique de SOAP 1.2 alors que l’utilisation de FaultExceptions avec basicHttpBinding a pour résultat la sémantique de SOAP 1.1.

J'utilise le code suivant pour lancer une exception FaultException < FaultDetails >:

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

La classe FaultDetails est simplement une classe de test contenant une chaîne " Message " comme vous pouvez le voir ci-dessous.

Lorsque vous utilisez wsHttpBinding, la réponse est:

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

Cela semble juste selon les spécifications de SOAP 1.2. Le répertoire principal / racine & # 8220; Code & # 8221; est & # 8220; l'expéditeur & # 8221 ;, qui a un & # 8220; sous-code & # 8221; de & # 8220; MySubFaultCode & # 8221 ;. Si le client / service client utilise WCF, FaultException côté client imite également la même structure, avec faultException.Code.Name étant & # 8220; Sender & # 8221; et faultException.Code.SubCode.Name étant & # 8220; MySubFaultCode & # 8221;.

Lorsque vous utilisez basicHttpBinding, la réponse est la suivante:

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

Cela ne semble pas correct. En regardant les spécifications de SOAP 1.1, je m'attendais à voir le & # 8220; faultcode & # 8221; avoir une valeur de & # 8220; s: Client.MySubFaultCode & # 8221; lorsque j'utilise FaultCode.CreateSenderFaultCode (nouveau FaultCode (& "; MySubFaultCode &")). De plus, un client WCF obtient une structure incorrecte. FaultException.Code.Name est & # 8220; MySubFaultCode & # 8221; au lieu d'être & # 8220; Expéditeur & # 8221 ;, et le faultException.Code.SubCode est null au lieu de faultException.Code.SubCode.Name étant & # 8220; MySubFaultCode & # 8221;. De plus, faultException.Code.IsSenderFault est false.

Problème similaire lors de l’utilisation de FaultCode.CreateReceiverFaultCode (nouveau FaultCode (& "MySubFaultCode &";)):

  • fonctionne comme prévu pour SOAP 1.2
  • génère & # 8220; s: MySubFaultCode & # 8221; au lieu de & # 8220; s: Server.MySubFaultCode & # 8221; et la faultException.Code.IsReceiverFault est false pour SOAP 1.1

Cet élément a également été posté par quelqu'un d'autre sur http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1 en 2006 et personne n'y a répondu. Je trouve très difficile de croire que personne ne l’a encore rencontré.

Voici quelqu'un d'autre qui rencontre un problème similaire: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3883110 & amp; SiteID = 1 & amp; mode = 1

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

Description du fonctionnement des erreurs: http://blogs.msdn.com/drnick/archive/2006/12/19/creating-faults-part-3.aspx

Est-ce que je fais quelque chose de mal ou est-ce vraiment un bogue dans WCF?

Était-ce utile?

La solution

Voici ma solution de contournement actuelle:

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

Malheureusement, je ne vois pas comment utiliser les sous-codes sans casser les clients SOAP 1.1 ou 1.2.

Si vous utilisez la syntaxe Code.SubCode, vous pouvez créer des valeurs de code de défaillance compatibles avec SOAP 1.1, mais cela rompt SOAP 1.2.

Si vous utilisez le support de sous-code approprié dans .NET (via les méthodes statiques FaultCode ou une des surcharges), il rompt SOAP 1.1 mais fonctionne dans SOAP 1.2.

Autres conseils

Réponse de Microsoft:

Comme indiqué dans http://msdn.microsoft.com/en-us /library/ms789039.aspx , deux méthodes sont décrites dans la spécification de Soap 1.1 pour les codes d’erreur personnalisés:

(1) Utilisation du " point " notation que vous décrivez

(2) Définition de nouveaux codes d'erreur

Malheureusement, le " point " la notation doit être évitée car son utilisation est déconseillée dans la spécification du profil de base WS-I. En gros, cela signifie qu’il n’ya pas d’équivalent réel du sous-code de défaillance Soap 1.2 lors de l’utilisation de Soap 1.1.

Ainsi, lors de la génération d'erreurs, vous devez connaître le MessageVersion défini dans la liaison et générer des codes d'erreur en conséquence.

Depuis " expéditeur " et " destinataire " Les codes d’erreur ne sont pas vaild pour Soap 1.1, et il n’existe pas d’équivalent réel d’un sous-code d’erreur, vous ne devez pas utiliser les méthodes CreateSenderFaultCode et CreateReceiverFaultCode lors de la génération de codes d’erreur personnalisés pour Soap 1.1.

Au lieu de cela, vous devrez définir votre propre code d'erreur, en utilisant votre propre espace de noms et votre nom:

FaultCode customFaultCode = new FaultCode (localName, faultNamespace);

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top