Pregunta

Tengo un cliente WCF que se comunica con una implementación de servidor desconocida sobre la que no tengo control. Este cliente funciona bien, simplemente no le gusta, lo que parece ser, mensajes de error SOAP incorrectamente formados. Los mensajes que recibo se ven así:

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

Creo que, de acuerdo con el esquema de jabón, los elementos secundarios no deben estar calificados y deben tener el siguiente aspecto:

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

¿Hay algo que pueda configurar o anular para poder consumir mensajes que lleguen en el último formato para poder consumir los mensajes de error en lugar de las excepciones xml?

¿Fue útil?

Solución

No puedo recordar cómo me topé con los inspectores de mensajes, pero es cómo resolví mi problema.

Esto y este artículo proporcionó la base para crear el inspector, y Lo que sigue es la carne del inspector:

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

Otros consejos

Parece que la aplicación ofensiva está utilizando una biblioteca SOAP personalizada (y mal implementada). El siguiente artículo podría ayudar (no he tenido que lidiar con esto hasta ahora, ya que estoy en una tienda .Net pura).

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

Tenga en cuenta que la clase System.Web.Services.Protocols.SoapHttpClientProtocol parece significativamente más tolerante a las respuestas de fallo mal formadas que WCF.

Esto se conoce a veces como protocolo de servicios ASMX. Esa puede ser una opción a considerar también.

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

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top