Ebraheem
Ebraheem

Reputation: 703

Unable to deserialize property with specific name

I'm using DataContractSerializer in C# to deserialize xml file into object, and everything was working fine :)

My issue started when I add a new property to my class and xml file. My new property name is EncryptionKey every time I deserialize file, property value remain null, but when i change the name of xml element and property to anEncryptionKey it deserialized correctly without changing anything else in the code.

Actually I try a lot of options for property name like EncryptKey, Encrypt and a lot more but I ended up with anEncryptionKey.

Maybe there is some constraint on properties names or something like that or I just need more caffeine to figure it out.

Xml file:

<?xml version="1.0" encoding="utf-8" ?>
<KioskSettings xmlns="http://schemas.datacontract.org/2004/07/Proxies" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <ID>20198</ID>
  <HeartBeatInterval>1</HeartBeatInterval>
  <ServerURL></ServerURL>
  <EncryptionKey>abcd</EncryptionKey>
</KioskSettings>

Code i use to deserialize file into object:

private KioskSettings ReadEngineSettingsFromSimulatorXmlFile()
 {
    KioskSettings engineSettings = new KioskSettings();
    DataContractSerializer serializer = new DataContractSerializer(typeof(KioskSettings));
    FileStream fs = new FileStream(@"c:\simulation.xml", FileMode.Open);
    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element:
                if (serializer.IsStartObject(reader))
                {
                    engineSettings = (KioskSettings)serializer.ReadObject(reader);
                }
                break;
        }
    }

    fs.Flush(); fs.Close();
    reader.Close(); 
    reader = null;
    serializer = null;
    return engineSettings;
}

KioskSettings class:

 public class KioskSettings
 {
    public string ID { get; set; }

    public int HeartBeatInterval {get; set;}

    public string ServerURL {get; set;}

    public string EncryptionKey { get; set; }

 }

Note: Above code may contains some syntax errors because I modify it to make it short.

Upvotes: 1

Views: 1062

Answers (1)

openshac
openshac

Reputation: 5155

You need to ensure your XML nodes are in alphabetical order:

<?xml version="1.0" encoding="utf-8" ?>
<KioskSettings xmlns="http://schemas.datacontract.org/2004/07/Proxies" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <EncryptionKey>abcd</EncryptionKey>
  <HeartBeatInterval>1</HeartBeatInterval>
  <ID>20198</ID>
  <ServerURL></ServerURL>
</KioskSettings>

Serialize a KioskSettings object with the following code, and ensure your XML takes the same form:

public static string DataContractSerializeObject<T>(T objectToSerialize)
{
    using (MemoryStream memStm = new MemoryStream())
    {
        var serializer = new DataContractSerializer(typeof(T));
        serializer.WriteObject(memStm, objectToSerialize);

        memStm.Seek(0, SeekOrigin.Begin);

        using (var streamReader = new StreamReader(memStm))
        {
            string result = streamReader.ReadToEnd();
            return result;
        }
    }
}

If you need to preserve a specific order then specify the DataMember attribute on your class properties - Data Member Order e.g.

[DataContract]
public class KioskSettings
{
    [DataMember(Order = 1)]
    public string ID { get; set; }

    [DataMember(Order = 2)]
    public int HeartBeatInterval { get; set; }

    [DataMember(Order = 3)]
    public string ServerURL { get; set; }

    [DataMember(Order = 4)]
    public string EncryptionKey { get; set; }
}

Upvotes: 2

Related Questions