2016-06-03 1 views
2

Lorsque vous utilisez le sérialiseur DataContract, il ne parvient pas à désérialiser la valeur Id comme dans l'exemple ci-dessous:DataContract ne désérialiser Id DataMember

using System; 
using System.Runtime.Serialization; 
using System.Xml.Linq; 

public class Program 
{ 
    private const string SAMPLE_VALIDATION_RESULT_XML = @" <ValidationResult> 
     <Message>The FooBar record has duplicate key values.</Message> 
     <Id>Microsoft.LightSwitch.EntityObject.DuplicateKey</Id> 
     <Target>http://localhost:55815/ApplicationData.svc/FooBar(0)</Target> 
    </ValidationResult>"; 

    [DataContract(Name = "ValidationResult", Namespace = "")] 
    public class ValidationResult 
    { 
     [DataMember] 
     public string Message { get; set; } 
     [DataMember] 
     public string Id { get; set; } 
     [DataMember] 
     public string Target { get; set; } 
    } 


    public static void Main() 
    { 
     var doc = XDocument.Parse(SAMPLE_VALIDATION_RESULT_XML); 
     using (var reader = doc.CreateReader()) 
     { 
      reader.MoveToContent(); 
      var res = (new DataContractSerializer(typeof(ValidationResult))).ReadObject(reader) as ValidationResult; 
      Console.WriteLine($"res.Id = \"{res.Id}\", expected \"Microsoft.LightSwitch.EntityObject.DuplicateKey\""); 
     } 
    } 
} 

Je devine que c'est à voir avec les caractéristiques d'intégrité référentielle, mais J'ai seulement trouvé une option pour désactiver cela (sur le DataContractSerializer), et cela n'a pas affecté le résultat.

Je ne peux pas changer le nom du champ Id, car il s'agit d'une API tierce, alors comment puis-je accéder à cette valeur?

+1

Ce code 'ReadObject (lecteur) en tant que ValidationResult' est considéré comme incorrect. Puisque vous savez que ce sera toujours un 'ValidationResult', vous devriez utiliser une distribution explicite. –

Répondre

3

Indiquez ordre des membres

[DataContract(Name = "ValidationResult", Namespace = "")] 
public class ValidationResult 
{ 
    [DataMember(Order = 0)] 
    public string Message { get; set; } 
    [DataMember(Order = 1)] 
    public string Id { get; set; } 
    [DataMember(Order = 2)] 
    public string Target { get; set; } 
} 

Sans spécifier un ordre, le DataContractSerializer espère que les membres seront dans l'ordre alphabétique. Voir Basic rules. Il est évident que l'ordre établi par le fournisseur de services. Donc vous devez le spécifier.

+0

Cela semble un peu fragile - je ne suis pas certain que le fournisseur d'API les renverra toujours dans le bon ordre. –

+0

@LiamDawson - voir mise à jour. Désolé pour mon mauvais anglais. –

+0

Ugh, ça craint. Je suis surpris qu'ils aient ajouté cette restriction. –

1

Utilisez ceci à la place. Le XmlSerializer ne se soucie pas de l'ordre.

var xml = new XmlSerializer(typeof(ValidationResult)); 
var res = (ValidationResult)xml.Deserialize(reader); 
+1

Je vais probablement utiliser cette approche, cependant, j'ai marqué l'autre comme la réponse parce qu'elle répond à la question implicite («pourquoi ça ne marche pas?»). –

+0

Je ferais la même chose. Ma réponse, même utile, est une solution de rechange. –