Why ORDER attribute by default?

Mar 17, 2010 at 4:17 AM

We have recently migrated from ASMX style services and proxies to WCF-style services and proxies for their entire middleware of 250+ services. Due to their extensive use of XSDs and to maintain backward compatibility, the WCF proxies are generated with the XmlSerialzer flag. What they discovered today was that the WCF proxy generates an Order attribute on each element whereas the older ASMX style proxy did not do that. As a result their client proxies are now tighly coupled with the exact order of the members in the service contract. So even though the contract does not logically change, switching the order of elements on the service breaks all the clients of that service and forces them to re-fresh their proxies.

 Question: Why was a design change made to use the Order attribute by default as opposed to keeping backward compatibility with the ASMX style proxies? (Incidentally, this behavior is also in VS 2010)

 

Add Service Reference (XmlSerializer)

 

        /// <remarks/>

        [System.Xml.Serialization.XmlElementAttribute(Order=0)]

        public string Field1 {

            get {

                return this.field1Field;

            }

            set {

                this.field1Field = value;            }

        }

Regards,

Prashant Nayak

Developer
Mar 17, 2010 at 8:52 AM
Edited Mar 17, 2010 at 2:41 PM

Hi Prashant,

I believe the problem here is that the default ordering of members serialized with the XmlSerializer is based on the reflection order of the members. This means that when another member is added to the data contract the likelihood of it breaking the member ordering is reasonably high. The Order property on the XmlElementAttribute was added in .NET 2.0 to fix this very issue, and prior to that you had no real control over member ordering. The tooling for ASMX web services (Add Web Reference) was built before .NET 2.0 introduced the Order property and was likely never updated to use the new feature. When the new tooling for WCF web services (Add Service Reference) was built it makes sense that Microsoft would start generating data contracts that utilize the new Order property to prevent ordering issues from happening again in the future. You will find that this is now always the case for the XmlSerializer.

The advice on MSDN for data contract versioning (when schema validation is not required) is rather interesting. This particular advice applies to DataContract types:

The Order property on the DataMemberAttribute should be used to make sure that all of the newly added data members appear after the existing data members. The recommended way of doing this is as follows: None of the data members in the first version of the data contract should have their Order property set. All of the data members added in version 2 of the data contract should have their Order property set to 2. All of the data members added in version 3 of the data contract should have their Order set to 3, and so on. It is permissible to have more than one data member set to the same Order number.

Even though the documentation does not provide a reason for the recommendation it does make sense. When serializing DataContract types whose DataMemberAttribute does not have the Order property set, the member ordering defaults to being alphabetical. This means that you have fixed member ordering for the first version of the data contract, even though it seems fairly implicit if you don't have prior knowledge of the behaviour. Then in the next version after setting the Order property of the new members to the same value, they will be grouped together after the original members, and in alphabetical order within the group. In this way the ordering remains deterministic.

You will find that when generating data contract types for the DataContractSerializer, the Order property of the DataMemberAttribute is not set until the first member that is out of alphabetical order is encountered. The Order property value will then be set to match the ordinal position of that member, and all following members will have a strictly monotonically increasing sequence for their Order property. In this regard Microsoft is not exactly following the advice described above; no doubt advice that was determined after the WCF tooling was built and shipped.

We could add a feature to WSCF.blue that removes the Order property from the XmlElementAttribute to provide a level of compatibility with the older ASMX generated proxies. It would also make sense to add the same feature for the DataContractSerializer when support for it is added to WSCF.blue. In this case it would not be for compatibility, but rather to allow you to more easily follow the data contract versioning advice from Microsoft.

I hope that clears things up for you.

Cheers,

Alex.

Developer
Mar 21, 2010 at 1:49 PM

Hi Prashant,

I just remembered that we already have the option to remove the Order property. The Visual Studio tooling has this option turned on by default with no way to turn it off. You could generate your clients using WSCF.blue and make sure the 'Order identifiers' option is not selected. The Order property will not be set on the XmlElementAttribute. The MessageBodyMemberAttribute will probably still have the Order property set but hopefully that will not cause any problems.

Cheers,

Alex.