Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Some properties are not being deserialized using DataContractSerializer

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.

like image 249
MarcinJuraszek Avatar asked Nov 14 '13 22:11

MarcinJuraszek


People also ask

How do you serialize an object in WCF?

This code constructs an instance of the DataContractSerializer that can be used only to serialize or deserialize instances of the Person class. DataContractSerializer dcs = new DataContractSerializer(typeof(Person)); // This can now be used to serialize/deserialize Person but not PurchaseOrder.

Which namespace is used for serialization in WCF?

By default WCF uses the DataContractSerializer class to serialize data types.

What is by serialization with respect to WCF?

The process forms a sequence of bytes into a logical object; this is called an encoding process. At runtime when WCF receives the logical message, it transforms them back into corresponding . Net objects. This process is called serialization.

What is data contract serializer?

Most important, the DataContractSerializer is used to serialize and deserialize data sent in Windows Communication Foundation (WCF) messages. Apply the DataContractAttribute attribute to classes, and the DataMemberAttribute attribute to class members to specify properties and fields that are serialized.


1 Answers

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; }
    }
like image 96
Patrick Huber Avatar answered Sep 19 '22 13:09

Patrick Huber