2009-09-22 68 views
1

我正在使用C#从Java-web服务读取数据。反序列化WCF服务时更改文化

我在VS2008中创建了一个Service引用到服务器,并且可以调用那个方法。然而,一些返回的字段的类型为十进制的,并且自动生成的WCF代理获取XML回失败了的CommunicationException说:

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

[编辑]这是一个完整的堆栈跟踪:

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) 

我可以看到,返回的十进制数被格式化为小数点的标点符号。出于测试目的,我尝试了Decimal.Parse(“123.99”)并得到了相同的错误。通过设置一个

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

之前我的测试代码为Decimal.Parse(“123.99”)我得到那个工作。

但是,在调用WCFService方法之前设置CurrentCulture并没有什么区别。

有没有什么方法可以让我的WCFService代理对象了解返回的XML是以另一种文化格式?

回答

2

您是否尝试过使用自定义IClientMessageFormatter.DeserializeReply()实现? WCF用扩展点填充到鳃中,所以很难知道选择哪一个,但DeserializeReply看起来是这个工作的正确工具。

看看this blog post-- sorry its original site is offline so pointing to Internet Archive version,它看起来类似于您正在尝试做的事情:使用WCF客户端调用非WCF Web服务,并对非客户端的帐户进行专门的处理,服务器上类似于WCF的行为。

下面是从博客中摘录的代码:

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); 
} 
+0

事实上,我的问题修正通过编辑谁做的web服务的家伙给我的.xsd文件。 (有一个.wsdl文件,和两个.xsd的)。你得到了分数,因为这似乎是一个很好的解决方案和良好的联系,但我没有真正尝试过。 – 2009-10-01 14:08:13

+0

你应该至少粘贴博客文章中最相关的代码 - 链接已经死了 – 2017-03-07 12:35:37

+0

对不起@CamiloTerevinto - 这是在7年前我写这篇文章的时候,早在“必须粘贴代码和链接”之前很长一段时间练习已正式化。我在Internet Archive上找到了博客,并使用存档链接和代码示例摘录更新了我的答案。 – 2017-03-08 03:16:43

0

我会感到非常惊讶,如果文化是真正的问题。 XML规范说,小数点使用点作为分隔符,(de)序列化程序知道这一点。你可以追踪这条消息,看看941位置有什么吗? (顺便说一下,除了WCF跟踪之外,我喜欢SoapUI)当涉及到小数时,也许不同的精度可能是一个问题:也许Java服务在尾部7之前放置更多的666666666666以防止三分之二的错误。净小数可以处理?

0

还有第二种选择:小数不是真的小数(再次:跟踪消息将是非常有启发性的)。我发现this link对于亚马逊服务感到有些遗憾,可能会将该单元放入十进制值(顺便说一句:WTF !?)。但是,在使用IClientMessageInspector接口将其传递到反序列化之前,如何与原始消息进行交互有一个很好的描述。如果这种奇怪的情况是您的问题,您可以强制服务提供商遵守他自己的合同或做这样的伎俩(如果提供商超出了您的控制范围并且说“这是设计上的”)。