Question

J'ai un client WCF communiquant avec une implémentation de serveur inconnue sur laquelle je n'ai aucun contrôle. Ce client fonctionne bien, il n'aime pas ce qui semble être des messages de faute SOAP mal formés. Les messages que je reçois ressemblent à:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">   
    <soap:Header>...</soap:Header>  
    <soap:Body>  
        <soap:Fault>  
            <soap:faultcode>soap:Client</soap:faultcode>  
            <soap:faultstring>...</soap:faultstring>  
            <soap:detail>...</soap:detail>  
        </soap:Fault>  
    </soap:Body>  
</soap:Envelope>  

Je pense que, selon le schéma soap, les éléments enfants ne doivent pas être qualifiés et ressembler à:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">   
    <soap:Header>...</soap:Header>  
    <soap:Body>  
        <soap:Fault>  
            <faultcode>soap:Client</faultcode>  
            <faultstring>...</faultstring>  
            <detail>...</detail>  
        </soap:Fault>  
    </soap:Body> 
</soap:Envelope>

Y a-t-il quelque chose que je peux configurer ou remplacer afin que je puisse consommer les messages qui arrivent dans ce dernier format afin que je puisse consommer les messages d'erreur au lieu d'exceptions xml?

Était-ce utile?

La solution

Je ne me souviens plus comment j'ai trouvé des inspecteurs de messages, mais c'est comme ça que j'ai résolu mon problème.

Ceci et cet article a fourni la base pour la création de l'inspecteur, et ce qui suit est la viande de l'inspecteur:

public void AfterReceiveReply(ref Message reply, object correlationState)
{
    if (!reply.IsFault)
        return;

    var document = new XmlDocument();

    document.Load(reply.GetReaderAtBodyContents());

    var navigator = document.CreateNavigator();
    var manager = new XmlNamespaceManager(navigator.NameTable);

    manager.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");

    var it = navigator.Select("//soap:Fault", manager);

    if (it.MoveNext() && it.Current.HasChildren && it.Current.MoveToChild(XPathNodeType.Element))
    {
        do
        {
            var c = it.Current;

            if (string.IsNullOrEmpty(c.Prefix))
                continue;

            c.ReplaceSelf("<" + c.LocalName + ">" + c.InnerXml + "</" + c.LocalName + ">");

            /// we may want to record the detail included inside the detail element, 
            /// it is not reported in the FaultException that is raised.

        } while (it.Current.MoveToNext());
    }

    var reader = XmlDictionaryReader.CreateDictionaryReader(new XmlNodeReader(document));

    reader.MoveToStartElement();

    var fixedReply = Message.CreateMessage(reply.Version, null, reader);

    fixedReply.Headers.CopyHeadersFrom(reply.Headers);
    fixedReply.Properties.CopyProperties(reply.Properties);

    reply = fixedReply;
}

Autres conseils

Il semble que l'application incriminée utilise une bibliothèque SOAP personnalisée (et mal implémentée). L’article suivant pourrait vous aider (je n’ai pas encore eu à traiter cette question car je suis dans un pur magasin .Net).

http://msdn.microsoft.com/en-us/library /ms733721.aspx

Notez que la classe System.Web.Services.Protocols.SoapHttpClientProtocol semble nettement plus tolérante aux réponses d'erreur mal formées que WCF.

Ceci est parfois appelé protocole de services ASMX. C'est peut-être une option à envisager également.

Howard Hoffman

} catch (SoapFaultClientException e) {
    log.error(e);
    SoapFaultDetail soapFaultDetail = e.getSoapFault().getFaultDetail();
    SoapFaultDetailElement detailElementChild = (SoapFaultDetailElement) soapFaultDetail.getDetailEntries().next();
    Source detailSource = detailElementChild.getSource();

    try {
        Object detail = (JAXBElement<SearchResponse>) getWebServiceTemplate().getUnmarshaller().unmarshal(detailSource);
//                throw new SoapFaultWithDetailException(detail);

    } catch (IOException e1) {
        throw new IllegalArgumentException("cannot unmarshal SOAP fault detail object: " + soapFaultDetail.getSource());
    }

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