2013-03-14 122 views
14

我有一個返回下列數據的Web服務:反序列化的XML與DataContractSerializer的

<?xml version=""1.0"" encoding=""UTF-8""?> 
<RESPONSE> 
    <KEY>12345</KEY> 
    <PROPERTY> 
     <PROPERTY_ADDRESS> 
      <STREET_NUM>25</STREET_NUM> 
      <STREET_ADDRESS>ELM ST</STREET_ADDRESS> 
      <STREET_PREFIX/> 
      <STREET_NAME>ELM</STREET_NAME> 
      <STREET_TYPE>ST</STREET_TYPE> 
      <STREET_SUFFIX/> 
     </PROPERTY_ADDRESS> 
    </PROPERTY> 
</RESPONSE> 

我有一類結構相匹配:

[DataContract(Name="RESPONSE", Namespace="")] 
public class Response 
{ 
    [DataMember(Name="KEY")] 
    public string Key { get; set; } 

    [DataMember(Name = "PROPERTY")] 
    public Property Property { get; set; } 
} 

[DataContract(Name="PROPERTY", Namespace="")] 
public class Property 
{ 
    [DataMember(Name="PROPERTY_ADDRESS")] 
    public PropertyAddress Address { get; set; } 
} 


[DataContract(Name="PROPERTY_ADDRESS", Namespace="")] 
public class PropertyAddress 
{ 
    [DataMember(Name="STREET_NUM")] 
    public string StreetNumber { get; set; } 

    [DataMember(Name = "STREET_ADDRESS")] 
    public string StreetAddress { get; set; } 

    [DataMember(Name = "STREET_PREFIX")] 
    public string StreetPrefix { get; set; } 

    [DataMember(Name = "STREET_NAME")] 
    public string StreetName { get; set; } 

    [DataMember(Name = "STREET_TYPE")] 
    public string StreetType { get; set; } 

    [DataMember(Name = "STREET_SUFFIX")] 
    public string StreetSuffix { get; set; } 
} 

我反序列化的代碼如下所示:

[Test] 
public void TestMapping() 
{ 
    var serializer = new DataContractSerializer(typeof(Response)); 

    Response response = null; 

    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(XmlData))) 
    { 
     response = (Response)serializer.ReadObject(ms); 
    } 

    //This works 
    Assert.AreEqual("12345", response.Key); 

    //This works 
    Assert.AreEqual("25", response.Property.Address.StreetNumber); 

    //This FAILS. StreetAddress is null 
    Assert.AreEqual("ELM ST", response.Property.Address.StreetAddress); 
} 

對於我的生活,我無法弄清楚爲什麼StreetAddress失敗。這很簡單,我錯過了。

+0

什麼樣的價值,你在那些財產,恰好,你可以做每財產testcontext.writeline看到價值。 – 2013-03-14 15:35:42

+0

response.Property.Address.StreetNumber ==「25」 response.Property.Address.StreetAddress == null – Micah 2013-03-14 15:36:24

+0

將StreetAddress更改爲int以查看它是否屬性名稱或類型失敗。 – 2013-03-14 15:42:13

回答

23

DataContractSerializer希望事情是in alphabetical order。您需要將Order添加到您的數據成員才能正常工作。

[DataContract(Name = "PROPERTY_ADDRESS", Namespace = "")] 
public class PropertyAddress 
{ 
    [DataMember(Name = "STREET_NUM", Order=0)] 
    public string StreetNumber { get; set; } 

    [DataMember(Name = "STREET_ADDRESS", Order=1)] 
    public string StreetAddress { get; set; } 

    [DataMember(Name = "STREET_PREFIX", Order=2)] 
    public string StreetPrefix { get; set; } 

    [DataMember(Name = "STREET_NAME", Order=3)] 
    public string StreetName { get; set; } 

    [DataMember(Name = "STREET_TYPE", Order=4)] 
    public string StreetType { get; set; } 

    [DataMember(Name = "STREET_SUFFIX",Order=5)] 
    public string StreetSuffix { get; set; } 
} 
+0

@Micah:它的性能原因。通過以特定順序預期標籤,DataContractSerializer可以節省將合同標籤與消息標籤進行匹配的時間。如果沒有明確指定,則必須有一些默認的順序。 – Vizu 2013-03-14 16:47:25

+19

我認爲任何'性能'收益都被浪費的開發人員在試圖發現,調試和修復這個愚蠢的需求時所浪費的大量時間所抵消。 – 2013-07-01 08:29:12

+0

所以...你如何禁用這種行爲? – BrainSlugs83 2013-09-27 22:30:27

6

你必須增強與元素的順序數據合同,因爲DataContractSerializer的預期元素被默認字母順序排序。你的XML不是這種情況。

下面的代碼:

[DataContract(Name = "PROPERTY_ADDRESS", Namespace = "")] 
public class PropertyAddress 
{ 
    [DataMember(Name = "STREET_NUM", Order=1)] 
    public string StreetNumber { get; set; } 

    [DataMember(Name = "STREET_ADDRESS", Order=2)] 
    public string StreetAddress { get; set; } 

    [DataMember(Name = "STREET_PREFIX", Order=3)] 
    public string StreetPrefix { get; set; } 

    [DataMember(Name = "STREET_NAME", Order=4)] 
    public string StreetName { get; set; } 

    [DataMember(Name = "STREET_TYPE", Order=5)] 
    public string StreetType { get; set; } 

    [DataMember(Name = "STREET_SUFFIX", Order=6)] 
    public string StreetSuffix { get; set; } 
}