Domanda

Ho un client WCF in comunicazione con un'implementazione del server sconosciuta su cui non ho alcun controllo. Questo client funziona bene, ma non gli piace, cosa sembra essere, messaggi SOAP Fault erroneamente formati. I messaggi che ricevo sembrano:

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

Credo che, secondo lo schema soap, gli elementi figlio non debbano essere qualificati e devono apparire come:

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

Esiste qualcosa che posso configurare o sovrascrivere in modo da poter utilizzare i messaggi che arrivano in quest'ultimo formato in modo da poter utilizzare i messaggi di errore anziché le eccezioni xml?

È stato utile?

Soluzione

Non riesco a ricordare come ho trovato inciampato su Message Inspector, ma che ho risolto il mio problema.

Questo e questo articolo ha fornito la base per la creazione dell'ispettore e ciò che segue è la carne dell'ispettore:

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

Altri suggerimenti

Sembra che l'applicazione offensiva stia utilizzando una libreria SOAP personalizzata (e implementata male). Il seguente articolo potrebbe essere d'aiuto (non ho ancora avuto a che fare con questo in quanto sono in un negozio .Net puro).

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

Si noti che la classe System.Web.Services.Protocols.SoapHttpClientProtocol sembra significativamente più tollerante alle risposte di errore non valide rispetto a WCF.

Talvolta viene definito protocollo dei servizi ASMX. Potrebbe anche essere un'opzione da considerare.

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

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top