Pages

Thursday, May 31, 2012

Versioning WCF Project




In this article I will be explaining Contract versioning in WCF.
Once the service is developed and rolled over to production, any changes in contracts should be backwards compatible so that existing clients are not affected when changes are deployed. We will explore the effects of changes in Data Contract and Service contracts and try to adopt a versioning strategy depending on the scenario.
I will explain further by examples


WCF Service:-

Contract:-
<ServiceContract(Namespace:="http://Microsoft.ServiceModel.10.00.00.01")>
Public Interface IService1
    <OperationContract()>
    Function GetData(ByVal value As IntegerAs String
End Interface

Implementation:-
Public Class Service1
    Implements IService1
    Public Function GetData(ByVal value As IntegerAs String Implements IService1.GetData
        Return String.Format("You entered: {0}", value)
    End Function
End Class

Web config:-
   <endpoint address="Demo1" binding="basicHttpBinding" contract="Service1.IService1"/>

Client 1:-

app.config:-
<endpoint address="http://localhost:51085/Service1.svc" binding="basicHttpBinding"
   bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
   name="BasicHttpBinding_IService1" />

Client class:-
  Sub Main()
        Dim serviceObj As New ServiceReference1.Service1Client
        Console.WriteLine(serviceObj.GetData(2).ToString())
        Console.ReadLine()
  End Sub

Now let’s assume we have 10 clients who are consuming the service, in the same manner as above.20 more clients are interested in consuming our service or some of our existing clients need more functionality or modify some function. We have to keep version of this, since all other clients can continue using the old service and we do can keep track of changes.
We can version our service by using date or build number in namespace. Example:-

WCF Service:-

Contract:-
<ServiceContract(Namespace:="http://Microsoft.ServiceModel. 10.00.00.01")>
Public Interface IService1
    <OperationContract()>
    Function GetData(ByVal value As IntegerAs String
End Interface
<ServiceContract(Namespace:="http://Microsoft.ServiceModel. 10.00.00.02")>
Public Interface IService2
    Inherits IService1
    <OperationContract()>
    Function GetValue(ByVal value As IntegerAs String
End Interface

Implementation:-

Public Class Service1
    Implements IService2

    Public Function GetData(ByVal value As IntegerAs String Implements IService1.GetData
        Return String.Format("You entered: {0}", value)
    End Function


    Public Function GetValue(value As IntegerAs String Implements IService2.GetValue
        Return String.Format("You entered: {0}", value)
    End Function
End Class

Web config:-
<endpoint address="ep1" binding="basicHttpBinding" contract="Service1.IService1"/>
<endpoint address="ep2" binding="basicHttpBinding" contract="Service1.IService2"/>

Client 2:-

app.config:-
  <endpoint address="http://localhost:51085/Service1.svc" binding="basicHttpBinding"
  bindingConfiguration="BasicHttpBinding_IService2" contract="ServiceReference1.IService2"
                name="BasicHttpBinding_IService2" />

Client class:-
  Sub Main()
   Dim serviceObj As New ServiceReference1.Service2Client
        Console.WriteLine(serviceObj.GetData(5).ToString())
        Console.WriteLine(serviceObj.GetValue(10).ToString())
        Console.ReadLine()
  End Sub

Now all the existing client without any changes they can continue using the service as well as our new clients can use the new functionality by consuming the new endpoints.
Our service WSDL will have these namespaces like this.

No comments: