Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

WP7 - A DataContractSerializer Bug?

DZone's Guide to

WP7 - A DataContractSerializer Bug?

· Mobile Zone
Free Resource

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

As we saw in the previous article the DataContractSerializer is able to serialize and deserialize class hierarchies, let’s review the example again:
[DataContract]
public class Entity
{
	public int M1;

	[DataMember]
	public string P1 { get; set; }
}

[DataContract]
public class Derived : Entity
{
	[DataMember]
	public string P2 { get; set; }
}
...
// can serialize and deserialize derived classes and class hierarchies
Derived d = new Derived();
d.P1 = "base";
d.P2 = "derived";
string data = DataContractSerializerHelpers.Serialize(d);
MessageBox.Show(data);
Derived deser = DataContractSerializerHelpers.Deserialize<derived>(data);
// deser holds the correct values
MessageBox.Show(string.Format("Deserialized values, P1: {0} P2: {1}", deser.P1, deser.P2));</derived>

When you run the example you will see the the serialized stream data will look like:

<derived xmlns="http://schemas.datacontract.org/2004/07/WP7DataContractSerializerBug.Domain" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <p1>base</p1>
  <p2>derived</p2>
</derived>

And the object is also deserialized in a correct way.

But if your derived class DO NOT expose any public or [DataMember] marked member the DataContractSerializer will fail in persisting the object: it will just ignore any of the base class properties and the object will be serialized as empty, let’s see some sample code:

[DataContract]
public class Entity
{
	public int M1;

	[DataMember]
	public string P1 { get; set; }
}

[DataContract]
public class DerivedBug : Entity
{

}
...
// if the derived class has no public property or datamember the object is not serialized correctly:
// none of the base class properties are persisted
DerivedBug d = new DerivedBug();
d.P1 = "base";
string data = DataContractSerializerHelpers.Serialize(d);
MessageBox.Show(data);
DerivedBug deser = DataContractSerializerHelpers.Deserialize<derivedbug>(data);
// the object is deserialized but all its properties have the default values (that is P1 is null)
MessageBox.Show(string.Format("Deserialized values, P1: {0} (it should be 'base')", string.IsNullOrEmpty(deser.P1) ? "null" : deser.P1));</derivedbug>
When you serialize the ‘DerivedBug’ class, you will obtain a data stream like the following:
<derivedbug xmlns="http://schemas.datacontract.org/2004/07/WP7DataContractSerializerBug.Domain" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"></derivedbug>

This means that the object will exists, but its deserialized properties will have their default values (also you have to remember that your parameterless constructor will not be called too). So you will get back an empty instance of the DerivedBug class.

To workaround this issue you will have to add a ‘fake’ property to your class and just avoid using it (add proper documentation to explain why that property is there):

/// <summary>
/// This is a workaround to a bug in WP7 DataContractSerializer
/// where no data will be serialized for a class if it
/// doesn't have an explicit DataMember property or field.
/// </summary>
[DataMember]
public int U;

For a complete series of examples you can download the attached project:

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:

Published at DZone with permission of Alessandro Giorgetti, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}