2009-09-22 52 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接口將其傳遞到反序列化之前,如何與原始消息進行交互有一個很好的描述。如果這種奇怪的情況是您的問題,您可以強制服務提供商遵守他自己的合同或做這樣的伎倆(如果提供商超出了您的控制範圍並且說「這是設計上的」)。