Defining namespaces on DataMembers? (Schema versioning related)

I'm trying to use the schema versioning approach described in the TechEd 2005 session "Versioning Services and Contract on the .Net Framework" by Don Smith together with WCF (January CTP), but I'm kind of stuck.

The reason why I'm stuck is because I want to use two xml namespaces in the same DataContract, where one of the DataMembers should refer to a xml type defined in a second namespace.

An XML fragment for my DataContract-decorated type should look like this:

<Issue xmlns="urn:mytns" xmlns:ver="urn:mytns:versioning">
<Revision>2</Revision>
<Id>123</Id>
<Description>....</Description>
<ver:Revision2/>
<Created>2005-10-29 13:24:01</Created>
</Issue>

And then I want to define the type like this:
[DataContract(Name="Issue", Namespace="urn:mytns")]
public class Issue
{
private string _id;
private string _description;
private DateTime _created;

[DataMember(Name="Revision", Order=1, IsRequired=true)]
private int _revision = 2;

[DataMember(Order=2)]
public string Id {
get { return _id; }
set { _id = value; }
}

[DataMember(Order=3)]
public string Description {
get { return _description; }
set { _description = value; }
}

[DataMember(Name="Revision2", Order=4, Namespace="urn:mytns:versioning")
private string _revision2Delimiter;

[DataMember(Order=5)]
public DateTime Created {
get { return _created; }
set { _created = value; }
}
}

My problem (highlighted) with this code is that there is no such property as Namespace on the DataMemberAttribute class. When I tried to find some information on this I found a MS blog post[1] that (maybe by accident ) used this nonexistent property in a sample.

My idea right now is to go for the XmlSerializer instead of the XmlFormatter, since the XmlElementAttribute supports a namespace to be defined on a member. But it would be really nice to use the XmlFormatter due to performance and all the other reasons. But many of the answers on questions like this one seems to be: "Use the XmlSerializer if you need better control of the XML output". That's really sad, IMHO :).

Clues anyone

Thanks in advance!

[1] http://blogs.msdn.com/craigmcmurtry/archive/2006/02/01/522353.aspx




Answer this question

Defining namespaces on DataMembers? (Schema versioning related)

  • abhi.pandey

    Yes, it does.

    Our approach is contract-first, where the contracts are the wsdl (made by hand or wsdl tool, not generated by a toolkit) and xml schemas for the messages and data types. I.e message = GetSomethingRequest (and possibly GetSomethingResult) and data type could be the class I described in my initial post.

    To minimize the deployment effort we need to make it possible to maintain backward and forward compatibility with as few endpoints (over time) to maintain as possible.
    So we need to have the V1 client to talk to the V2 (and V3 and V4 ... ) service, and also the V2 (and V3 and V4 ... ) client to talk to the V1 service.

    And actually we're not talking versions, we're talking revisions here.
    If we want to change something significally, we need to make a new major version (changing the namespace) of our contracts.
    So basically our constraints for our versioning model (regarding messages) is that a service that implements a contract must respond with a message of the same major version (namespace), but not necessarily the same revision as the revision of the request message sent by the client.

    The schemas for this solution (based on the samples from Don Smith):
    MyTypes.xsd:
    Defines complex type Issue with elements Id, Description, Created and last, in the xs:sequence, a reference to an optional group called ver:IssueRevisions (revisions group for the Issue type). The ver prefix represents an import of Versioning.xsd.

    Versioning.xsd:
    Defines a group called IssueRevisions with a revision delimiter element called Revision1 and after that a <xs:any namespace="##other"/>

    So for instance, a fragment of the Issue type, revision 2, would look something like:
    <Issue xmlns="urn:mytns" xmlns:ver="urn:mytns-versioning">
    <Id>1234</Id>
    <Description>...</Description>
    <ver:Revision1/>
    <!-- End of elements defined in rev 1 schema -->
    <!-- here comes the xs:any part for rev 1 of the schema -->
    <Created>2006-02-17T13:12:14</Created>
    </Issue>

    To implement this model with DCs, we need to include have a DataMember called Revision1 in the Issue DC. If we do that we will get a Revision1 element that is defined in the local namespace and not in our versioning namespace.

    I know that for this approach, the XmlSerializer is better suited in order to control the XML that is being generated. But still I wanted to give the DCs a chance, and of course, also possibly get some feedback on why not to choose this model of versioning of contracts.

    I've also read the guidance about versioning service and data contracts, but the guidance tells me that one should create interfaces for each change, like IPurchaseOrderV1, IPurchaseOrderV2 etc.
    So with many minor changes, this produces a great number of types (one for each change/revision) in the service layer. IMHO, this is not a very good design.

    The reason we need schema validation is primarily because we need to perform automated tests that ensures us that changes made to the service implementation still conforms to each version of the contracts. I.e. we need to be sure that v1 clients (not in our control) doesn't fail when we deploy the v2 version of the service.
    I know that automated test suites that does schema validation aren't covering ALL things that can make an existing client to fail, but we have this requirement and schema validation seems good enough for our team.



  • martinnickel

    If you want to do Don's approach to versioning and you want a strongly-typed programming model -- you need to use the XmlSerializer for now.
  • tonn

    [DataContract] has its own versioning story.

    Does your versioning plans require the ability to do schema validation against the "v1" of the schema


  • Defining namespaces on DataMembers? (Schema versioning related)