views:

897

answers:

4

I'm using C# to read data from a Java-webservice.

I've created a Service reference in VS2008 to the server, and can call the one method that is there. However, a few of the fields returned are of type Decimal, and as the automatically generated WCF proxy gets XML back it fails with a CommunicationException saying:

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

[Edit] Here is a full stacktrace:

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)

I can see that the decimal number returned is formatted with a punctuation as the decimal. For testing purposes I tried a Decimal.Parse("123.99") and got the same error. By setting a

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

before my testcode for Decimal.Parse("123.99") I get that working.

However, setting the CurrentCulture before calling the WCFService method doesn't make any difference.

Are there any ways I can get my WCFService proxy object to understand that the returned XML is in another cultureformat?

+1  A: 

Have you tried using a custom IClientMessageFormatter.DeserializeReply() implementation? WCF is stuffed to the gills with extensibility points, so it's often hard to know which one to pick, but DeserializeReply looks like the right tool for this job.

Take a look at http://blogs.vertigo.com/personal/petar/Blog/archive/2008/06/23/twitter-wcf-client.aspx which looks like a similar thing to what you're trying to do: using a WCF client to call a non-WCF web service, and to do specialized processing of the response to account for non-WCF-like behavior on the server.

Justin Grant
I actually got the problem fixed by editing the .xsd file given to me by the guy who made the webservice. (Got a .wsdl file, and two .xsd's). You got the points since this seems like a good solution and good link, but I haven't actually tried it.
Frode Lillerud
A: 

I would be very surprised if the culture is really the problem. XML spec says that decimals are using the dot as separator, and the (de)serializer knows this. Can you trace the message and see what's in at position 941? (By the way: I like SoapUI for such things, besides WCF tracing) When it comes to decimals, maybe the different precision might be a problem: maybe the Java service puts more 666666666666 before the trailing 7 in case of two thirds that the .net decimal can handle?

Marc Wittke
A: 

And there is a second option: the decimal is not really a decimal (again: tracing the message would be very enlighting). I found this link which laments a little bit about the amazon services, that might put the unit into the decimal value (by the way: WTF!?). However, there is a nice description on how to interact with the raw message before passing it to the deserialization using the IClientMessageInspector interface. If such a strange case is your problem you could either force the service provider to comply with his own contract or do such a trick (if the provider is outside your sphere of control and says "this is by design").

Marc Wittke
+1  A: 

You could attach a culture initializer to a behaviour which you then add to an endpoint. This would set the culture on the thread deserializing the response, the field should therefore, be deserialized correctly.

For a code example of this, have a look at this link:

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

Shiraz Bhaiji