2013-03-14 68 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; } 
}