2013-03-14 19 views
14

Mam usługę internetową, która zwraca następujące dane:deserializacji XML z 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> 

Mam struktury klasowej, aby dopasować:

[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; } 
} 

Mój kod deserializacji wygląda następująco:

[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); 
} 

Dla życia mnie nie mogę zrozumieć, dlaczego StreetAddress zawodzi. To musi być coś prostego, czego mi brakuje.

+0

jakie wartości są otrzymujesz dokładnie w tych nieruchomości, można zrobić testcontext.writeline na każdej nieruchomości, aby zobaczyć wartość. –

+0

response.Property.Address.StreetNumber == "25" response.Property.Address.StreetAddress == null – Micah

+0

Zmień StreetAddress na int, aby zobaczyć, czy jest to nazwa właściwości lub błąd typu. –

Odpowiedz

23

DataContractSerializer oczekuje, że będzie to in alphabetical order. Musisz dodać Order do swoich Członków Danych, aby to działało poprawnie.

[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: To jest ze względu na wydajność. Oczekując tagów w określonej kolejności, DataContractSerializer może zaoszczędzić czas na dopasowaniu tagów kontraktu do tagów wiadomości. I musi być pewna kolejność domyślna, jeśli żadna nie jest określona jawnie. – Vizu

+19

Myślę, że wszelkie zyski "wydajności" są z nawiązką równoważone przez samą ilość zmarnowanego czasu programisty w poszukiwaniu, debugowaniu i naprawieniu tego głupiego wymogu. –

+0

Więc ... jak wyłączyć to zachowanie? – BrainSlugs83

6

Trzeba poszerzyć swoją umowę danych z rzędu elementów ponieważ DataContractSerializer spodziewa elementy mają być sortowane alfabetycznie domyślnie. Tak nie jest z twoim XML.

Oto kod:

[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; } 
} 
Powiązane problemy