[WCF] 使用Xml來Request WCF Service需注意Xml Element順序
前言
這兩天同事在寫Wcf REST Service的時候,遇到一個很奇怪的問題,
需求是這樣的,Request的資料型別為Xml,而Response為Json,
但在Request Xml資料時卻發現透過Wcf Deserialize之後,
Data Class的Property有些是Null的,但可以確認XML是完整送到Service端,
沒有遺漏任何訊息。
實際演練
接下來讓我們來重現當時的場景,
首先我們先定義一個Wcf REST Service 如下,
他可以透過Post來存取GetData Function
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare)]
string GetData(Comment value);
}
並定義好Function參數的Data Class
[DataContract(Namespace = "")]
public class Comment
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Body { get; set; }
}
我們使用Fiddler2來測試Post資料到Service
同時在Visual Studio裡面設Break point可以發現Body是Null的
但我們透過OperationContext.Current.RequestContext.RequestMessage可以看見,訊息是有完整收到的。
但如果我們改變Request Xml的順序,改成
<Comment>
<Body>123</Body>
<Name>kirk</Name>
</Comment>
再次查看可以發現,這次Property理面的資料都存在了
這是因為Wcf預設的DataContractSerializer 在解析Xml時會按照字母順序塞值,
而且不是每次都從頭尋找 (像已經塞值到Name時,就不會回頭塞Body,因為N的字母順序在B之後),
若我們希望按照自己想要的順序來排放XML的話,則需要在DataMember屬性加上Order如下
[DataContract(Namespace = "")]
public class Comment
{
[DataMember(Order=0)]
public string Name { get; set; }
[DataMember(Order = 1)]
public string Body { get; set; }
}
這樣我們就可以使用第一組XML來Request,並正確取得資料了。
備註:
- 若request和response都使用xml,我們可以在Class或Function加上XmlSerializeFormatAttribute,就可以不用擔心Xml的順序問題。
- 若request和response都使用json,也不需要擔心順序的問題
參考資料:
http://msdn.microsoft.com/en-us/library/ms729813.aspx
http://www.pluralsight-training.net/community/blogs/aaron/archive/2006/04/18/21950.aspx