WCF - handle versioning - wcf

If I need to go from this service contract:
[ServiceContract(Namespace="http://api.x.com/Svc1")]
public interface IService1
{
[OperationContract(Name = "AddCustomer")]
bool AddCustomer(DTOCustomer1 customer);
}
to this:
[ServiceContract(Namespace="http://api.x.com/Svc1")]
public interface IService1
{
[OperationContract(Name = "AddCustomer")]
bool AddCustomer(DTOCustomer2 customer);
}
and according to this good article: Versioning WCF I understand that when data contract is changed there is a need of defining a new vs of data contract in new namespace followed by defining a new vs of service contract in new namespace, after which a new endpoint should be added.
How exactly am I suppose to have this done. Is there an example anywhere? Could you write something based on my service contract shown above?
Thank you in advance!

According to the linked article you should do something like:
[ServiceContract(Namespace="http://api.x.com/Svc1")]
public interface IServiceNew : IService1
{
[OperationContract(Name = "AddCustomerNew")]
bool AddCustomer(DTOCustomer2 customer);
}
Then implement it in your service:
public class MyCurrentServiceImplementation : IServiceNew
{...}
You will need to redeploy your service but existing clients should be able to continue to call the AddCustomer operation, and new clients can call the AddCustomerNew operation.

It's very important to note that the assumption you state in your post:
"when data contract is changed there is a need of defining a new vs of
data contract in new namespace"
is not always true. See "Data Contract Versioning" on MSDN for a number of cases where a data contract change is non-breaking and may therefore require no action other than perhaps modifying the internal implementation of your service method to handle the presence/absence of certain data due to differences between data contract versions.
In this specific example I would question how two versions of a method called AddCustomer can vary so much in their intent that it justifies creating a new service interface. Without seeing your old and new data contracts I can't know for sure, but I'm guessing that the real issue here is that the method has evolved to accept additional customer information.
If that's true, then it's very much like the situation of optional arguments in a method call. WCF is designed to handle this scenario very nicely as a non-breaking change to the data contract. As long as you can follow the guidelines in "Best Practices: Data Contract Versioning" on MSDN, then calls supplying either the old or new version of the contract will be accepted just fine by your existing service interface. Your service method will get the data that is possible given the combination of the client and server data contracts.
I would keep my service interface coherent, simple, and clean (i.e. avoid doing things like IServiceNew) and instead just add to the data contract and modify the implementation of AddCustomer to adapt to the whatever data it receives.

Related

Using DLL references of WCF service in another WCF service

Sorry for the long question in the first place. I would rather prefer to come up with a shorter question but this is the most stripped version I could provide that I can clearly explain my point.
I have been trying to deliver a wrapper service to our client which should provide multiple services in it. Idea behind it is to reduce multiple calls to a one call and return a single object which has other associated objects in it. To illustrate my point, let me give following example:
Let's say we have following services:
MyCompany.Services.Donation
MyCompany.Services.Payment
MyCompany.Services.PartialPayment
Normally client should query Donation service (with a donationID) to get donation information, and then using the retrieved donation information, they should query Payment service to get payment related details, and if the payment is done in multiple small payments, using retrieved payment information, they should query PartialPayment service to get all donation information for a particular Donor.
Instead of client doing this, I am going to provide a wrapper service to accept donationID as a single parameter and return a class similar to this:
[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class DonationDetail
{
[DataMember]
public MyCompany.Services.Donation.Record donationRecord;
[DataMember]
public PaymentDetail paymentDetail;
}
[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class PaymentDetail
{
[DataMember]
public MyCompany.Services.Payment.Record paymentRecord;
[DataMember]
public List<MyCompany.Services.PartialPayment.Record> partialPayments;
}
So an instance of DonationDetail record should return all relevant information with that donation.
My problem arises when I use these individual services DLL's* in my wrapper service since any class I pass to client using wrapper service becomes part of the wrapper service and client can't use them right away with the corresponding types they retrieved using service references without writing a custom construction method to convert one type to another - although they are same objects. Instead of referring classes in original namespace, service uses following classes something like that now for the classes mentioned above:
DonationDetail.Record (Donation Record - I would expect MyCompany.Services.Donation.Record)
DonationDetail.Record1 (Payment Record - I would expect MyCompany.Services.Payment .Record)
DonationDetail.Record2 (PartialPayment Record - I would expect MyCompany.Services.PartialPayment.Record)
Is there a way to provide such an interface without a custom constructor? So, if they use "PartialPayment" namespace for the MyCompany.Services.PartialPayment WCF service, can they do something below after DonationDetail is retrieved via wrapper service?
PartialPayment.Record partialPayment = dDetailObj.paymentDetail.partialPayments[0];
*: Don't ask me why I don't use service references unless that is the cause of the problem, since that option gives me other problems to me at this point)
So I think what you are saying, effectively, is that if you have two different services that return the same object and when you add this as two different service references to the client, even though ultimately they are the same object as far as the services are concerned (since they reference the same DLL), the client sees them as two different types so you can't take the object returned from one and send it as the input to the other service.
Assuming I have understood your question (and I apologise if I have not)...
You could map one type to the other by constructing it and setting the properties but that is really kind of a pain and not very friendly to the consumer etc, hence I am going to suggest something kind of radical...
Ditch the service references on the client.
Yup, I said it, why would I suggest such a thing!?! Here's why...
First of all I would make sure my project was structured something like this:
Donation Detail Client Library
IDonationService (this is the service contract - notice no implementation in the client library)
DonationRecord
Payment Detail Client Library
IPaymentService (this is the service contract - notice no implementation in the client library)
PaymentRecord
Partial Payment Client Library
IPartialPaymentService (this is the service contract - notice no implementation in the client library)
PartialPaymentRecord
Wrapper Service Client Library (which references the three other client libraries)
IWrapperService (this is the service contract - notice no implementation in the client library)
Incidentally, I gave your records different class names but you could use namespaces if you like and call them all Record (I think calling them different names is less confusing, but that is probably just me).
On the service end you reference the client library that you need to implement the service and do whatever you have to do just as you always have.
On the client you reference the client libary (or libraries depending on what service you want to call) too, in the same way (so you effectively have a shared library between server and client - yeah old skool, but hey, you will see why).
The client then has the interface for the service contract and all the data contracts so it does not need the whole service reference, generated code thing. Instead what you can do on your client is something like this:
DonationRecord donation;
using (var cf = new ChannelFactory<IDonationService>("EndpointNameInConfigurationFile"))
{
IDonationService donationservice = cf.CreateChannel();
donation = donationservice.GetDonation("Donation1234");
}
using (var cf = new ChannelFactory<IWrapperService>("EndpointNameInConfigurationFile"))
{
IWrapperService wrapperService = cf.CreateChannel();
wrapperService.DoSomethingWithDonation(donation);
}
There, you see I took the data contract from one service and sent it to a completely unrelated service and it looks natural (I have an object that is returned from a method on class X and I took it and passed it as an agrument on class Y, job done, just like programming).
NOTE: Using this technique will not stop service references from working just as they always have so any existing client code would not have to change, just if you use your new wrapper service, you could use it like this to save having to map types.

WCF - contracts versioning (by example)

This should be easy for someone familiar with the best practices of versioning service/data contracts. I want to make sure that I will use this versioning in the correct way.
So, let's say we have a service contract:
[ServiceContract(Namespace="http://api.x.com/Svc1")]
public interface IService1
{
[OperationContract(Name = "AddCustomer")]
bool AddCustomer(DTOCustomer1 customer);
}
and data contract:
[DataContract(Name="Customer", Namespace="http://api.x.com/Svc1/2011/01/DTO")]
public class DTOCustomer1
{
[DataMember(Name="Name")]
public string Name { ... }
}
if I really need to change the latter into something else: (the following is just example)
[DataContract(Name="Customer", Namespace="http://api.x.com/Svc1/2012/01/DTO")]
public class DTOCustomer2
{
[DataMember(Name="Name")]
public string Name { ... }
[DataMember(Name="Address")]
public DTOAddress Address { ... }
}
...then how shall I use DTOCustomer2 instead of DTOCustomer1 from the service so that old and new clients will be compliant? What is recommended in this case? Will my service contract change? AFAIK I won't need to change the service contract. How will the service contract look like? Do I need a new endpoint? Do I need a new operation contract making use of the new data contract?
EDIT1:
Simply changing
bool AddCustomer(DTOCustomer1 customer);
into
bool AddCustomer(DTOCustomer2 customer);
will do?
EDIT2:
Answer to EDIT1 is No, since DTOCustomer2 has different namespace, but it might work if it has the same namespace. Still I don't know what is the best thing here and expect somebody to come up with a good answer.
Thank you in advance!
I ended up answering to this question with the help of another question here: WCF - handle versioning
Please find some useful links that describe the best practise for Data contract versioning.
Best Practices: Data Contract Versioning
Data Contract Versioning
The 2nd link describes on how you handle when you want to add or removed attributes of your data contract and few other scenarios.
Hope that helps.

Utilizing multiple service contracts over the same WCF channel or session

I'm in the process of writing a duplex WCF service using NetTcpBinding, and I've run into an architecture question that I think I know the answer to, but hope that I'm wrong.
Our service is stateful, and we've selected NetTcpBinding with PerSession InstanceContextMode. For various reasons, this is something that we require. I'm trying to break up our larger interface (where large blocks of the operations would not apply to many clients) into multiple smaller interfaces with the operations logically grouped. While it's simple enough to have a single service implementation implement all of the contracts, I'm not sure if it's possible to have multiple service contracts share a single channel (or, more to my requirement, a single session), and I'd definitely need to be able to do that in order to make this work.
I could, of course, include everything on one contract and throw FaultExceptions when an invalid operation is performed, but I'd really like to be able to break these up and not even add an endpoint for inapplicable contracts. Is what I'm looking for possible?
TL;DR Version:
I need to be able to do this:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
void Foo();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
void Bar();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IServiceA, IServiceB
{
...
}
And be able to establish one session from the client to the service but use both IServiceA and IServiceB.
The default instance provider over a sessionful channel will give you an instance per connection in your case. You can however extend the instance provider to pick up an existing object from your own cache and return the same object.
How you correlate instances will be upto you using some special message header etc. The underlying channel/Connection will be different for each proxy and also use differnt buffers / concurrency models but you can allow service model to use the same instance.
http://msdn.microsoft.com/en-us/magazine/cc163590.aspx

Request/Response pattern in SOA implementation

In some enterprise-like project (.NET, WCF) i saw that all service contracts accept a single Request parameter and always return Response:
[DataContract]
public class CustomerRequest : RequestBase {
[DataMember]
public long Id { get; set; }
}
[DataContract]
public class CustomerResponse : ResponseBase {
[DataMember]
public CustomerInfo Customer { get; set; }
}
where RequestBase/ResponseBase contain common stuff like ErrorCode, Context, etc. Bodies of both service methods and proxies are wrapped in try/catch, so the only way to check for errors is looking at ResponseBase.ErrorCode (which is enumeration).
I want to know how this technique is called and why it's better compared to passing what's needed as method parameters and using standard WCF context passing/faults mechanisms?
The pattern you are talking about is based on Contract First development. It is, however not necessary that you use the Error block pattern in WCF, you can still throw faultexceptions back to the client, instead of using the Error Xml block. The Error block has been used for a very long time and therefore, a lot of people are accustom to its use. Also, other platform developers (java for example) are not as familiar with faultExceptions, even though it is an industry standard.
http://docs.oasis-open.org/wsrf/wsrf-ws_base_faults-1.2-spec-os.pdf
The Request / Response pattern is very valuable in SOA (Service Oriented Architecture), and I would recommend using it rather than creating methods that take in parameters and pass back a value or object. You will see the benefits when you start creating your messages. As stated previously, they evolved from Contract First Development, where one would create the messages first using XSDs and generate your classes based on the XSDs. This process was used in classic web services to ensure all of your datatypes would serialize properly in SOAP. With the advent of WCF, the datacontractserializer is more intelligent and knows how to serialize types that would previously not serialize properly(e.g., ArrayLists, List, and so on).
The benefits of Request-Response Pattern are:
You can inherit all of your request and responses from base objects where you can maintain consistency for common properties (error block for example).
Web Services should by nature require as little documentation as possible. This pattern allows just that. Take for instance a method like public BusScheduleResponse GetBusScheduleByDateRange(BusDateRangeRequest request); The client will know by default what to pass in and what they are getting back, as well, when they build the request, they can see what is required and what is optional. Say this request has properties like Carriers [Flag Enum] (Required), StartDate(Required), EndDate(Required), PriceRange (optional), MinSeatsAvailable(Option), etc... you get the point.
When the user received the response, it can contain a lot more data than just the usual return object. Error block, Tracking information, whatever, use your imagination.
In the BusScheduleResponse Example, This could return Multiple Arrays of bus schedule information for multiple Carriers.
Hope this helps.
One word of caution. Don't get confused and think I am talking about generating your own [MessageContract]s. Your Requests and Responses are DataContracts. I just want to make sure I am not confusing you. No one should create their own MessageContracts in WCF, unless they have a really good reason to do so.

Adding a new parameter to a WCF operation: choices?

What's the best way to handle adding a new (optional) parameter to an existing operation without requiring the client to update their WSDL? I do not want to update the namespace to describe a new version of the service contracts, since this should be backwards compatible with older clients.
Should I add a new operation with a new parameter, as an overload? Or should I just add the parameter to the existing operation?
Here is my operation:
[OperationContract]
MyResponse GetData();
Should it be:
[OperationContract]
MyResponse GetData();
[OperationContract]
MyResponse GetData(string filter);
Or more simply, just change it to this:
[OperationContract]
MyResponse GetData(string filter);
The latter option seems best, and according to my reference book, "The impact on client is none. New parameters are initialized to default values at the service." Is WCF initializing it to the the so-called default value? If so, what is the default value?
One thing to take into consideration is that you can't have two OperationContracts with the same name. The way it's serialized it will throw an error.
The best approach is to go with Option 3 (just adding the new parameter) and within the method logic account for it being a null value for those clients that haven't updated yet. If it's a breaking change that the clients will need to update for, make sure to not have the entire application die because of the exception.
Well, changing an existing contract after it's been used is really against all rules of service orientation; you should never ever break an existing contract.
In reality, this happens quite frequently, and WCF is pretty good about handling that for you. As long as you only introduce non-breaking changes, existing clients will continue to work.
This can be:
a new operation contract on an existing service contract
a new non-required field on a DataContract
What you're trying to do is not going to work, though
you cannot have two method with the same name in WCF - WCF is not .NET and you cannot have two methods by the same name being different only by their signature. Doesn't work. You'll need to use two separate, distinct names. Remember: your WCF method calls will be translated into a WSDL (web service description language) document to describe the service - and WSDL simply does not support having two operations with the same name - just a difference in signature is not supported and will not work.
you cannot change the existing contract, e.g. you cannot introduce a new parameter into a method call after the fact, without breaking the contract.
So what you really need to do is this:
[OperationContract]
MyResponse GetData();
[OperationContract]
MyResponse GetFilteredData(string filter);
Any other change you suggested will a) break the contract, or b) simply not work in WCF:
you can try this:
[OperationContract]
MyResponse GetData();
[OperationContract(Name = "GetDataByFilter")]
MyResponse GetData(string filter);