Pregunta

Estoy usando C # para leer datos de un servicio web Java.

He creado una referencia de servicio en VS2008 al servidor, y puedo llamar a un método que está allí. Sin embargo, algunos de los campos devueltos son de tipo decimal y, como el proxy WCF genera automáticamente obtiene XML posterior falla con un CommunicationException diciendo:

"Error in deserializing body of reply message for operation 'getOpenReceivables'."
"There is an error in XML document (1, 941)."
"Input string was not in a correct format."

[Editar] He aquí una StackTrace completo:

at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt)   
at System.Decimal.Parse(String s, NumberStyles style, IFormatProvider provider)
at System.Xml.XmlConvert.ToDecimal(String s)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExecutePortType.Read2_XXNG_OPEN_RECEIVABLES(Boolean isNullable, Boolean checkType)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderExecutePortType.Read3_Item()  
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer.Deserialize(XmlSerializationReader reader)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)

Puedo ver que el número decimal devuelto está formateado con una puntuacion como el decimal. Para propósitos de prueba he intentado un Decimal.Parse ( "123.99") y consiguió el mismo error. Al establecer un

System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");

antes de mi testcode para Decimal.Parse ( "123.99") Puedo conseguir que el trabajo.

Sin embargo, el establecimiento de la CurrentCulture antes de llamar al método WCFService no hace ninguna diferencia.

¿Hay alguna manera puedo obtener mi WCFService objeto proxy de entender que el XML devuelto está en otra cultureformat?

¿Fue útil?

Solución

¿Ha intentado utilizar un IClientMessageFormatter .DeserializeReply () aplicación? WCF está lleno hasta los topes con puntos de extensibilidad, por lo que a menudo es difícil saber cuál elegir, pero DeserializeReply se parece a la herramienta adecuada para este trabajo.

Tome un vistazo a este blog post-- siento su sitio original está en línea por lo que apunta a Internet Archive versión que se parece a algo similar a lo que estás tratando de hacer : el uso de un cliente WCF para llamar a un servicio web WCF no, y para hacer el procesamiento especializado de la respuesta para tener en cuenta el comportamiento no WCF-como en el servidor.

He aquí un extracto de código a partir de ese blog:

public object DeserializeReply(Message message, object[] parameters)
{
    object helperInstance = Activator.CreateInstance(_return);

    //we have special condition where service sets Http response code to 403 that signals that an error has occured 
    KeyValuePair<string,object> serviceErrorProperty = message.Properties.FirstOrDefault(p => p.Key == ResponseErrorKey);
    if (serviceErrorProperty.Key != null)
    {
        //we have an error message
        IResponseErrorProvider responseErrorProvider = helperInstance as IResponseErrorProvider;
        if (responseErrorProvider != null)
        {
            //unpack the error payload from message and assign to the object
            ResponseError payload = message.GetBody<ResponseError>();
            responseErrorProvider.ServiceError = payload;

            //return fixed null type with error attached to it
            return helperInstance;
        }
    }

    //another message we might get is <nil-classes type="array"/> for empty arrays.
    XmlDictionaryReader xdr = message.GetReaderAtBodyContents();
    xdr.MoveToContent();

    if (xdr.Name == NullMessage)
    {
        return helperInstance; //standin for the null value
    }

    return _formatter.DeserializeReply(message, parameters);
}

public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
    return _formatter.SerializeRequest(messageVersion, parameters);
}

Otros consejos

Se puede adjuntar un inicializador de la cultura a un comportamiento que luego se agrega a un punto final. Esto establecería la cultura en la rosca deserializar la respuesta, el campo debe, por lo tanto, puede deserializar correctamente.

Para obtener un ejemplo de código de este, echar un vistazo a este enlace:

http : //blogs.msdn.com/drnick/archive/2008/02/26/using-call-context-initializers-for-culture.aspx

Me sorprendería mucho que la cultura es realmente el problema. especificación XML dice que los decimales están utilizando el punto como separador, y la (de) serializador sabe. Se puede rastrear el mensaje y ver lo que está en la posición 941? (Por cierto: me gusta SoapUI para este tipo de cosas, además de WCF calco) Cuando se trata de decimales, tal vez la precisión diferente podría ser un problema: puede que el servicio de Java pone más 666666666666 antes del 7 de fuga en caso de que dos tercios del punto decimal .net puede manejar

Y hay una segunda opción: el decimal no es realmente un decimal (de nuevo: trazando el mensaje sería muy ideas ilustradas). He encontrado este enlace , que se lamenta un poco acerca de los servicios de Amazon, que podrían poner la unidad en el valor decimal (por cierto: WTF !?). Sin embargo, hay una buena descripción sobre cómo interactuar con el mensaje prima antes de pasarlo a la deserialización mediante la interfaz IClientMessageInspector. Si un caso tan extraño es su problema que podría obligar al proveedor de servicios para cumplir con su contrato o hacer un truco como (si el proveedor está fuera de su esfera de control y dice "esto es por diseño").

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