· One likely scenario is that you will add new operations without changing the existing service contract. But, you may want to support these new operations at the same endpoint. You can achieve this by creating a new contract that inherits the old contract, adding new operations to the new one. Consider the contract shown in Example 2-8 as the first published version of the service contract.
[ServiceContract(Name="ServiceAContract",
Namespace = "http://www.thatindigogirl.com/samples/2006/06")]
public interface IServiceA
{
[OperationContract]
string Operation1();
[OperationContract]
string Operation2();
}
· The endpoint configuration for the service implementing the contract might look like this:
<endpoint address="ServiceA" contract="BusinessServiceContracts.IServiceA" binding="basicHttpBinding" />
· When new operations are added to the service to extend its features, you may want to expose the same endpoint to old and new clients while still somehow tracking the contract version related to new features. If you extend the original service contract you can add operations under a new namespace as shown in Example 2-9.
[ServiceContract(Name="ServiceAContract",
Namespace = "http://www.thatindigogirl.com/samples/2006/08")]
public interface IServiceA2:IServiceA
{
[OperationContract]
string Operation3();
}
· Note the service contract name is the same, but the namespace has changed. The service type can implement IServiceA2 and it will be able to expose the original operations with their original namespace, while exposing the new operation with the versioned namespace. As such, original clients can hit the same endpoint without impact, while new clients who download the metadata when version 2 is available, can access all operations.
· This scenario does not address the following:
You can’t modify existing operations with contract inheritance
You can’t differentiate old clients from new clients since they hit the same endpoint
· Another approach would be to version the entire contract and create a new endpoint for new clients. In this case, version 2 of the contract might look like that in Example 2-10.
[ServiceContract(Name="ServiceAContract2",
Namespace = "http://www.thatindigogirl.com/samples/2006/08")]
public interface IServiceA2
{
[OperationContract]
string Operation1();
[OperationContract]
string Operation2();
[OperationContract]
string Operation3();
}
· In order to provide a unique WSDL containing only one or the other contract, a unique service type must be created to implement the new contract. Both versions of the service can still share implementation behind the scenes.
· With this implementation the following applies:
You can differentiate old and new clients by service entry point
You can modify existing operations in the new interface (not recommended, you should really provide new operation names)
New clients cannot send messages to the original endpoint
Old clients cannot send messages to the new endpoint
To summarize the discussion of service contract versioning, Figure 2-4 and Figure 2-5 illustrate the decision flow for non-strict and strict-versioning policy, respectively.
Non-strict versioning allows you to add or remove parameters without versioning the service contract. This also means that the implementation code must accommodate how to handle version 1 and version 2 clients. Though possible, the idea of operation signatures changes can be very difficult to track, whereas a data contract as the service operation parameter at least allows for explicitly required and non-required parameters (to be discussed in the "Data Contracts" section of this chapter).
With strict service contract versioning, any change to an operation leads to a new service contract. A new endpoint is always provided to ensure version 2 clients can be differentiated from version 1 clients.