Best Practices for Versioning

Versioning, in the context of data contracts, is all about schema validation because the entity that is consumed and used at the end of the schema itself. It is the changes to this schema you need to version. Versioning for data contracts can be divided into two groups—one that requires schema validation and a second that does not. The first group where schema validation is required is quite rare in today's enterprise environment, and many systems can handle the fact that certain elements are extra and not defined in a schema.

With Schema Validation

Data contracts should be considered immutable when schema validation is required "both ways" (that is, new to old, and vice versa). You should create a new data contract whenever a new version is required, because this will generate a new schema. This new data contract should also incorporate the relevant name, namespace, and updated service type information. In most cases, changes to data contracts in these circumstances need to be rippled across to every layer in the solution. This means if a data contract is part of another data contract and if the child data contract is updated, even though the parent is not, then the parent data contract would need to be versioned as well.

It is quite common that in a heterogeneous environment you do not have control over the incoming messages, though usually you do have some degree of control on the outgoing messages. If there is a requirement that the messages that are generated (that is, the outgoing messages) need to strictly comply with a schema, then you would need to turn off the round-tripping feature. Round-tripping is when the original incoming message, which you have no control over, has extra information that does not comply with your schema. This extra information is stored and then returned with the outgoing message. When this happens, if the outgoing message needs to be compliant with a schema, it won't be. You have two options to switch off round-tripping. One option is not to implement IExtensibleDataObject, and the second is to set the IngoreExtensionDataObject property to true on the [ServiceBehavior] attribute.

Without Schema Validation

When schema validation is not required, the guidelines for versioning are as follows:

  • Type inheritance should not be used to version data contracts; instead, either create a new type or change the data contract on an existing type.

  • Always implement the interface IExtensibleDataObject to support round-tripping.

  • Do not change the name or namespace for the data contract because the versions for that data contract evolve. If the underlying type changes, then make appropriate changes to keep the data contract the same, for example, by using the Name property.

  • Similar to the data contract point earlier, do not change any names or namespaces for the data members. If the underlying data member (such as field, property, event, and so on) changes, preserve the data member by using the Name property. Also, changing either the type or the order of any of the data member is not allowed because in most cases doing so will also cause the data contract to change.

  • When there is a new version containing new data members, they should always follow these rules:

    • For the new member, the IsRequired property should be set to false (the default value).

    • A callback method using the [OnDeserializing] attribute should be provided in cases where a default value of null or zero for a data member is not acceptable. This should provide the default value that will be acceptable by the data member.

    • In the "old" version of the data contract, the Order property should not be set. Any new members added in subsequent versions should have their Order property set to that version. For example, version 2 of the data contract should have the Order property set to 2, version 3 to 3, and so on. The order of all the newly added members should be after the existing members; you can use the Order property to ensure this.

  • Data members should not be removed even if the IsRequired property is set to false.

  • The IsRequired property cannot be changed between versions.

  • The EmitDefaultValue property cannot be changed for the required data members (that is, have the IsRequired property set to true) between versions.

  • When creating a new version, do not create a branched version hierarchy.

  • Enumerations are just like any other data members, and the same practices for reordering, adding, removing, and so on, apply as stated previously.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset