WCF — Be ware of the field ordering when using DataContractSerializer

One of the less known aspect of the Dat­a­Con­tract­Se­ri­al­iz­er is its depen­den­cy on the order in which fields are seri­al­ized and dese­ri­al­ized.

As this arti­cle points out, the basic rules for order­ing include:

  • If a data con­tract type is a part of an inher­i­tance hier­ar­chy, data mem­bers of its base types are always first in the order.
  • Next in order are the cur­rent type’s data mem­bers that do not have the Order prop­er­ty of the DataMem­ber­At­tribute attribute set, in alpha­bet­i­cal order.
  • Next are any data mem­bers that have the Order prop­er­ty of the DataMem­ber­At­tribute attribute set. These are ordered by the val­ue of the Order prop­er­ty first and then alpha­bet­i­cal­ly if there is more than one mem­ber of a cer­tain Order val­ue. Order val­ues may be skipped.

The prob­lem is that when the inbound data is not ordered accord­ing­ly the fields which are ‘out of order’ will not be dese­ri­al­ized as high­light­ed by this Stack­Over­flow ques­tion. Though this is unlike­ly to hap­pen as the seri­al­iz­er will take care of the cor­rect order­ing for you, unless like jhersh you are attempt­ing to man­u­al­ly cre­ate some data for test pur­pos­es.

Parting Thoughts…

See­ing as the Dat­a­Con­tract­Se­ri­al­iz­er is also depen­dent on the order­ing of the fields in the seri­al­ized type (albeit not trans­par­ent to you and well tak­en care of almost all the time) I have long been tempt­ed to try out the Pro­to­col Buffers wrap­per for .Net which are meant to be much faster and more com­pact because it doesn’t seri­al­ize the names of the prop­er­ties unlike the Dat­a­Con­tract­Se­ri­al­iz­er.

For those of you who aren’t aware of it, pro­to­col buffers is the bina­ry seri­al­iza­tion used by Google for most of its data com­mu­ni­ca­tions. In order to use the pro­to­buf-net seri­al­iza­tion you need to explic­it­ly spec­i­fy the order in which your prop­er­ties should be seri­al­ized:

[DataContract]
public sealed class Test1
{
    [DataMember(Name="a", Order=1, IsRequired=true)]
    public int A { get; set; }
}

[DataContract]
public sealed class Test2
{
    [DataMember(Name = "b", Order = 2, IsRequired = true)]
    public string B { get; set; }
}

[DataContract]
public sealed class Test3
{
    [DataMember(Name = "c", Order = 3, IsRequired = true)]
    public Test1 C { get; set; }
}

And inject a new behav­iour to the WCFmethod to use the new seri­al­iz­er:

[ServiceContract]
public interface IFoo
{
    [OperationContract, ProtoBehavior]
    Test3 Bar(Test1 value);
}

Oh, such temp­ta­tion…

References:

Stack­Over­flow ques­tion – WCF data con­tract, some fields do not seri­al­ize

MSDN – Data mem­ber order

pro­to­buf-net — Is it quick?