Some properties are not being deserialized using DataContractSerializer
Asked Answered
A

1

11

I have a problem with DataContractSerializer. I use it to create class instances from XML returned by ASP.NET Web Service. But actually the source of data is not important here. To make the whole case easier to debug I've created a simple test project with just the serialization and problem still occurs.

Here is my 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>

The class I'm trying to deserialize XML to:

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

And my serialization helper class:

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

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

Test code:

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

After setting brakepoint at the end of the method I see following:

enter image description here

As you can see, both AverageExecutionTime and InitialCount are not deserialized and have int default value. They should to set to 43 and 1, because these values are in the XML.

It's even more strange to me, that UserCount property is done right, but actually it does not differ at all from the two which doesn't work at all. The only thing is different is element name.

Altorilievo answered 14/11, 2013 at 22:35 Comment(1)
Possible duplicate #15413968Semiannual
H
13

I managed to get it to work by updating the data contract. Something to do with the order. When I made Uri a required property it threw an exception, so it may be something to do with the load order.

    [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; }
    }
House answered 14/11, 2013 at 23:17 Comment(3)
Do you have any idea why it does not work without Order/IsRequired?Altorilievo
@Altorilievo I did two tests, Removed all of the IsRequired and Order properties and changed the input xml to alphabetically order the elements. worked Removed the IsRequired and kept the order as is. worked It appears the serializer is using your class to stream read the document. If you don't specify order, it doesn't know to look for the elements in the correct sequence. By default the sequence used is alphabetical.House
@Altorilievo The DataContractSerializer uses/expects a strict ordering of the elements in the XML per the documentation here. If your XML elements will not appear in the default order per the rules, then you need specify the order in the [DataMember] attribute as shown in Patrick's answer.Blent

© 2022 - 2024 — McMap. All rights reserved.