DataContract versioning is required when a modification has been made to the existing DataContract exposed to the client from the service or vice versa. If either service or client changes the schema of DataContract exposed, then a new version of DataContract is needed and both parties involved in communication should be able to accommodate the changes done in the DataContract.
The scenario that can cause for a new version of DataContract is as below,
- Missing a member from existing DataContract.
- Adding a new member to existing DataContract.
- Round Tripping
In this article we will explore New Member scenarios.
Adding a New Member to existing DataContract
This is most common changes we do to give new version to DataContract.
For example we have a DataContract through which we are exposing Product custom class to the client
Product.cs
[DataContract]
public class Product
{
[DataMember(Order = 1)]
public string ProductNumber;
[DataMember(Order = 2)]
public string ProductName;
[DataMember(Order = 3)]
public string ProductPrice;
}
And we have ServiceContract which is returning a Product from the service
IService1.cs
namespace WcfService10
{
[ServiceContract]
public interface IService1
{
[OperationContract]
Product GetaProduct();
}
}
Service implementation is as below:
Service1.svc.cs
namespace WcfService10
{
public class Service1 : IService1
{
public Product GetaProduct()
{
try
{
Product p = new Product { ProductName = "Pen", ProductPrice = "9", ProductNumber = "1" };
return p;
}
catch (Exception ex)
{
return null;
}
}
}
}
Now at the client side, we can call the service as below. (Call this client as Client1)
Program.cs
using ConsoleApplication1.ServiceReference1;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (Service1Client proxy = new Service1Client())
{
var res = proxy.GetaProduct();
Console.WriteLine(res.ProductName + res.ProductPrice + res.ProductNumber);
}
Console.ReadKey(true);
}
}
}
Output
Now let us go ahead and modify the DataContract at the service. Just add one more parameter
[DataMember(Order = 4)]
public string ProductColor;
So now DataContract will look like
Product.cs
[DataContract]
public class Product
{
[DataMember(Order = 1)]
public string ProductNumber;
[DataMember(Order = 2)]
public string ProductName;
[DataMember(Order = 3)]
public string ProductPrice;
[DataMember(Order = 4)]
public string ProductColor;
}
And now go ahead and modify the service implementation as below:
Service1.svc.cs
namespace WcfService10
{
public class Service1 : IService1
{
public Product GetaProduct()
{
try
{
Product p = new Product { ProductName = "Pen", ProductPrice = "9", ProductNumber = "1",ProductColor="Red" };
return p;
}
catch (Exception ex)
{
return null;
}
}
}
}
Now do not update the service reference at the clien1. What I mean here is that same version of DataContract at the client 1. And create one more client and call it as client 2. Use updated service at the client.
So, now client 1 will look like exactly it was previously
Program.cs (Client1)
using ConsoleApplication1.ServiceReference1;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (Service1Client proxy = new Service1Client())
{
var res = proxy.GetaProduct();
Console.WriteLine(res.ProductName + res.ProductPrice + res.ProductNumber);
}
Console.ReadKey(true);
}
}
}
Output would be exactly the same as it was with previous version of DataContract
And new created client (Client2) will look like below,
Program.cs(Client2)
using ConsoleApplication2.ServiceReference1;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
using (Service1Client proxy = new Service1Client())
{
var res = proxy.GetaProduct();
Console.WriteLine(res.ProductName + res.ProductPrice + res.ProductNumber+res.ProductColor);
}
Console.ReadKey(true);
}
}
}
This client is using version2 of DataContract and output would contain newly added member in DataContract.
So on deseralization new added DataMember will be ingnored by DataContractSeralizer and both party will continue working without breaking.