Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Disable Deserialization Order Sensitivity

You can specify the serialization order by decorating the elements in your data contract:

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

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

So you can make sure the serialization order is the same all the time. But there is no way to tell the deserializer to "forget" about the order - the point is: this is handled by means of an XML schema, and done using the <xs:sequence> element - and that does imply and require order. You cannot just turn that off, I'm afraid.

Based on that XML schema, your non-.NET clients should be able to verify whether or not their XML that they're about to send conforms to that schema - and if it doesn't because the Bar and ID element have been swapped, they shouldn't be sending that invalid XML.


You can use the IsRequired property of the DataMember attribute to specify that the elements are required. In that way, instead of getting "mysterious" null value, you'll get a more explicit error message indicating that a required element is missing.

[DataContract]
public class Foo 
{ 
  [DataMember(IsRequired=true, Order=1)]
  public int ID { get; set; } 

  [DataMember(IsRequired=true, Order=2)]
  public int Bar { get; set; } 
}

What's happening in your case is:

  • The DataContract expects Bar and ID elements in that order (alphabetic because you haven't specified an explicit order).

  • It encounters an ID element without a preceding Bar element. Since Bar is not required, it simply ignores it.

  • The ID element following Bar is ignored because it is in the wrong position.

Having said that, setting IsRequired to true will only help in version 1 of your contract. Elements added in subsequent versions will normally have IsRequired set to false. MSDN has an article on data contract versioning.


There's an old thread on this here:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/a891928b-d27a-4ef2-83b3-ee407c6b9187

Looks like the only option is to swap the serializer, but then it becomes opt in which is even more annoying.

Edit: you could write your own serializer to re-order the elements and then pass it on to DataContractSerializer.