views:

782

answers:

3

What's the best way to handle adding a new (optional) parameter to an existing opertion 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?

+1  A: 

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

  1. 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.

  2. 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:

marc_s
I actually went with your suggestion, but Agent_9191's answer was more correct regarding my original question, so I accepted his answer and +1'ed yours.
Mike Atlas
+5  A: 

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.

Agent_9191
It is a non-breaking change. I'll handle if the filter is null or empty gracefully.
Mike Atlas
@Mike: I don't think it's non-breaking - suddenly, your method "GetData" now expects a parameter that is not being supplied by the original callers....
marc_s
@marc_s: due to the flexibility of WCF as long at the value can be null, a client who doesn't pass something to it will still work. That's the advantage of allowing version-mismatching in WCF.
Agent_9191
+2  A: 

you can try this:

[OperationContract]
MyResponse GetData(); 

[OperationContract(Name = "GetDataByFilter")]
MyResponse GetData(string filter);
sami