【问题标题】:Change culture when deserializing WCF service反序列化 WCF 服务时更改文化
【发布时间】:2009-09-22 13:19:17
【问题描述】:

我正在使用 C# 从 Java 网络服务读取数据。

我在 VS2008 中创建了对服务器的服务引用,并且可以调用那里的一种方法。但是,返回的一些字段是 Decimal 类型,当自动生成的 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 是另一种文化格式?

【问题讨论】:

    标签: c# wcf cultureinfo


    【解决方案1】:

    您是否尝试过使用自定义 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);
    }
    

    【讨论】:

    • 我实际上是通过编辑制作 web 服务的人给我的 .xsd 文件解决了这个问题。 (有一个 .wsdl 文件和两个 .xsd 文件)。你得到了分数,因为这似乎是一个很好的解决方案和很好的链接,但我还没有真正尝试过。
    • 您至少应该粘贴了博客文章中最相关的代码——链接已失效
    • 对不起@CamiloTerevinto - 我写这篇文章的时间差不多是 7 年前,早在“必须将代码与链接一起粘贴”最佳实践正式形成之前。我在 Internet 存档上找到了该博客,并使用存档链接和代码示例摘录更新了我的答案。
    【解决方案2】:

    您可以将文化初始化程序附加到行为,然后将其添加到端点。这将在反序列化响应的线程上设置文化,因此应该正确反序列化该字段。

    有关此代码示例,请查看此链接:

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

    【讨论】:

      【解决方案3】:

      如果文化真的是问题所在,我会感到非常惊讶。 XML 规范说小数使用点作为分隔符,(反)序列化器知道这一点。你能追踪消息并查看 941 位置的内容吗? (顺便说一句:除了 WCF 跟踪,我喜欢 SoapUI 这样的事情)当涉及到小数时,不同的精度可能是一个问题:如果三分之二的情况下,Java 服务可能会在尾随的 7 之前放置更多的 666666666666 .net小数可以处理吗?

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-11-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多