C# 反序列化WCF服务时更改区域性

C# 反序列化WCF服务时更改区域性,c#,wcf,cultureinfo,C#,Wcf,Cultureinfo,我正在使用C#从Java Web服务读取数据 我在VS2008中创建了一个对服务器的服务引用,可以调用其中的一个方法。但是,返回的一些字段是Decimal类型的,当自动生成的WCF代理返回XML时,它会失败,并出现一个CommunicationException,说明: "Error in deserializing body of reply message for operation 'getOpenReceivables'." "There is an error in XML docum

我正在使用C#从Java Web服务读取数据

我在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位于另一个cultureformat中吗?

您是否尝试过使用自定义实现?WCF充满了扩展性点,因此通常很难知道选择哪一个,但反序列化似乎是这项工作的合适工具

看一看与您尝试执行的操作类似的操作:使用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);
}
public对象反序列化reply(消息消息,对象[]参数)
{
object helperInstance=Activator.CreateInstance(_return);
//我们有一个特殊的条件,服务将Http响应代码设置为403,表示发生了错误
KeyValuePair serviceErrorProperty=message.Properties.FirstOrDefault(p=>p.Key==ResponseErrorKey);
if(serviceErrorProperty.Key!=null)
{
//我们收到一条错误消息
IResponseErrorProvider responseErrorProvider=helperInstance as IResponseErrorProvider;
if(responseErrorProvider!=null)
{
//从消息中解压缩错误负载并分配给对象
ResponseError有效负载=message.GetBody();
responseErrorProvider.ServiceError=有效负载;
//返回固定的空类型,并附加错误
返回帮助者立场;
}
}
//我们可能得到的另一条消息是空数组。
XmlDictionaryReader xdr=message.GetReaderAtBodyContents();
xdr.MoveToContent();
if(xdr.Name==NullMessage)
{
return helperInstance;//表示空值
}
返回_formatter.DeserializeReply(消息、参数);
}
公共消息序列化请求(MessageVersion MessageVersion,对象[]参数)
{
返回格式化程序.SerializeRequest(messageVersion,参数);
}

如果文化真的是问题所在,我会非常惊讶。XML规范说小数使用点作为分隔符,(反)序列化程序知道这一点。你能追踪信息,看看941号位置有什么吗?(顺便说一句:除了WCF跟踪之外,我喜欢这些东西)当谈到小数时,可能不同的精度可能是一个问题:如果.net decimal可以处理三分之二的小数,Java服务可能会在后面的7之前放置更多的666666?

还有第二个选项:小数实际上不是小数(再次强调:跟踪消息将非常有启发性)。我发现,对于amazon服务有一点遗憾,这可能会将单位转换为十进制值(顺便说一下:WTF!)。但是,对于如何在使用IClientMessageInspector接口将原始消息传递给反序列化之前与原始消息进行交互,有一个很好的描述。如果这种奇怪的情况是您的问题,您可以强制服务提供商遵守其自己的合同,也可以采取这样的措施(如果提供程序不在您的控制范围内,并说“这是设计的”)。

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

有关这方面的代码示例,请查看以下链接:


实际上,我通过编辑制作Web服务的人给我的.xsd文件解决了这个问题。(有一个.wsdl文件和两个.xsd文件)。你得到了要点,因为这似乎是一个很好的解决方案和很好的链接,但我实际上没有尝试过。你至少应该粘贴博客文章中最相关的代码——链接是deadsorry@CamiloTerevinto——这是我写这篇文章的时候差不多7年前的事了,远远早于“必须将代码与链接一起粘贴”的时间最佳实践被正式化了。我在互联网档案中找到了博客,并用档案链接和代码示例摘录更新了我的答案。