When you have to introduce a breaking change in a ServiceContract, a best practice is to keep the old one and create开发者_开发知识库 a new one, and use some version identifier in the namespace.
If I understand this correctly, I should be able to do the following:
[ServiceContract(Namespace = "http://foo.com/2010/01/14")]
public interface IVersionedService
{
[OperationContract]
string WriteGreeting(Person person);
}
[ServiceContract(Name = "IVersionedService", Namespace = "http://foo.com/2010/02/21")]
public interface IVersionedService2
{
[OperationContract(Name = "WriteGreeting")]
Greeting WriteGreeting2(Person2 person);
}
With this I can create a service that supports both versions. This actually works, and it looks fine when testing from soapUI.
However, when I create a client in Visual Studio using "Add Service Reference", VS disregards the namespaces and simply sees two interfaces with the same name. In order to differentiate them, VS adds "1" to the name of one of them. I end up with proxies called
ServiceReference.VersionedServiceClient
and
ServiceReference.VersionedService1Client
Now it's not easy for anybody to see which is the newer version.
Should I give the interfaces different names? E.g
IVersionedService1
IVersionedService2
or
IVersionedService/2010/01/14
IVersionedService/2010/02/21
Doesn't this defeat the purpose of the namespace?
Should I put them in different service classes and get a unique URL for each version?
Well, typically, you would not have a service implementation that implements both the old and the new interface at the same time. Therefore, if a new client comes along and connects to your new service, it would only get the new interface and all is fine.
If you need to be able to offer up both interfaces, then yes - you need to do some "magic" to make this possible:
if you can, derive the new interface from the old. This works as long as you're only adding on new stuff. A new service implementation would then implement both the old-style interface, as well as the new
public interface IVersionedService2 : IVersionService1 { [OperationContract(Name = "WriteNewGreeting")] Greeting WriteNewGreeting(Person2 person); }
So your service implementation would then have both a
WriteGreeting
as well as aWriteNewGreeting
method - the new clients could connect to and use either, while older clients would still see their IVersionService1 interface and the "old" namespace, and thus be able to continue to call your serviceif you cannot derive the new service from the old, create a completely new service, and expose it on a new endpoint, e.g. a new address or port. That way, existing clients can keep on calling the existing and well known service, while new ones can be directed to a separate service on a separate endpoint and things should be fine for them, too
精彩评论