2013-11-14 11 views
10

Ho un problema con DataContractSerializer. Lo uso per creare istanze di classi da XML restituite dal servizio Web ASP.NET. Ma in realtà la fonte dei dati non è importante qui. Per rendere l'intero caso più facile da eseguire il debug, ho creato un semplice progetto di test con solo la serializzazione e il problema si verifica ancora.Alcune proprietà non vengono deserializzate utilizzando DataContractSerializer

Ecco il mio XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<GetTestURL p1:type="MyApp.GetTestUrlInfo" xmlns:p1="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices"> 
    <TestURL>http://bing.com</TestURL> 
    <UserCount p1:type="Edm.Int32">1</UserCount> 
    <InitialCount p1:type="Edm.Int32">1</InitialCount> 
    <AverageExecutionTime p1:type="Edm.Int32">43</AverageExecutionTime> 
</GetTestURL> 

La classe che sto cercando di deserializzare XML:

[DataContract(Name = "GetTestURL", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")] 
public class TestInfo 
{ 
    [DataMember(Name = "TestURL")] 
    public Uri TestUri { get; private set; } 

    [DataMember(Name = "UserCount")] 
    public int UserCount { get; private set; } 

    [DataMember(Name = "InitialCount")] 
    public int InitialCount { get; private set; } 

    [DataMember(Name = "AverageExecutionTime")] 
    public int AverageExecutionTime { get; private set; } 
} 

E il mio serializzazione classe helper: codice

public static class SerializationHelper<T> 
{ 
    private static DataContractSerializer _serializer = new DataContractSerializer(typeof(T)); 

    public static T Deserialize(Stream source) 
    { 
     return (T)_serializer.ReadObject(source); 
    } 
} 

di prova:

// Test program 
public static void Main() 
{ 
    TestInfo info = null; 
    using (var stream = File.Open("Input.xml", FileMode.Open, FileAccess.Read)) 
    { 
     info = SerializationHelper<TestInfo>.Deserialize(stream); 
    } 
} 

Dopo aver impostato brakepoint alla fine del metodo vedo seguente:

enter image description here

Come si può vedere, sia AverageExecutionTime e InitialCount non sono deserializzati e hanno int valore predefinito. Dovrebbero essere impostati su 43 e 1, perché questi valori sono nell'XML.

È ancora più strano per me che la proprietà UserCount sia eseguita correttamente, ma in realtà non differisce affatto da quelle che non funzionano affatto. L'unica cosa è diversa è il nome dell'elemento.

+0

Eventuali duplicati http://stackoverflow.com/questions/15413468/deserializing-xml-with-datacontractserializer?rq=1 –

risposta

10

Sono riuscito a farlo funzionare aggiornando il contratto dati. Qualcosa a che fare con l'ordine. Quando ho reso Uri una proprietà richiesta, ha generato un'eccezione, quindi potrebbe essere qualcosa a che fare con l'ordine di caricamento.

[DataContract(Name = "GetTestURL", Namespace = "http://schemas.microsoft.com/ado/2007/08/dataservices")] 
    public class TestInfo 
    { 
     public TestInfo() { } 
     public TestInfo(Uri uri, int userCount, int initialCount, int averageExecutionTime) 
     { 
      TestUri = uri; 
      UserCount = userCount; 
      InitialCount = initialCount; 
      AverageExecutionTime = averageExecutionTime; 
     } 
     [DataMember(Name = "TestURL", IsRequired=true, Order=1)] 
     public Uri TestUri { get; private set; } 

     [DataMember(Name = "UserCount", IsRequired=true, Order=2)] 
     public int UserCount { get; private set; } 

     [DataMember(Name = "InitialCount", IsRequired=true, Order=3)] 
     public int InitialCount { get; private set; } 

     [DataMember(Name = "AverageExecutionTime", IsRequired=true, Order=4)] 
     public int AverageExecutionTime { get; private set; } 
    } 
+0

Avete qualche idea del perché non funziona senza 'Order' /' IsRequired' ? – MarcinJuraszek

+1

@MarcinJuraszek Ho effettuato due test, Rimosso tutte le proprietà IsRequired e Order e modificato l'input xml in ordine alfabetico per gli elementi. * lavorato * Rimosso il valore IsRequired e mantenuto l'ordine così com'è. * funzionava * Sembra che il serializzatore stia usando la tua classe per leggere il documento in streaming. Se non si specifica l'ordine, non è sicuro cercare gli elementi nella sequenza corretta. Di default la sequenza utilizzata è alfabetica. –

+4

@MarcinJuraszek 'DataContractSerializer' utilizza/prevede un rigoroso ordinamento degli elementi nell'XML per la documentazione [qui] (http://msdn.microsoft.com/en-us/library/ms729813.aspx). Se i tuoi elementi XML non appariranno nell'ordine predefinito secondo le regole, dovrai specificare l'ordine nell'attributo '[DataMember]' come mostrato nella risposta di Patrick. –