WCF Versioning : Update Attribute Namespaces and Support Previous Namespaces

痴心易碎 提交于 2021-02-11 18:13:56

问题


I have three WCF services (.svc) which generate .wsdl references for SOAP messages.

Given that part of the namespace needs to change for all ServiceContract, OperationContract, DataContract attributes, for example

[DataContract(Namespace = "http://old.com.au/types/")]

to

[DataContract(Namespace = "http://new.com.au/types/")]

How is it that I can still support clients which have the old service reference (without them needing to update, because maybe they wont have time to update immediately) and allow clients getting a new service reference to get the new namespace? None of the service is changing, just the namespace.

So far I have read a lot of stuff but the following article suggests it is possible to change the service type from the ServiceHostFactory : http://blog.ranamauro.com/2008/07/hosting-wcf-service-on-iis-site-with_25.html

Which would mean creating two of every contract (putting as much of the implementation as possible in one place), and figuring out at runtime which serivce type to use. This would create some mess in my scenario.

Q. Is there an alternative, nice way to accomplish this or is it expected that this kind of thing should not be done and the client made to update to the new namespace.

(If there is a namespace mismatch from the client I get the error : The message with Action "..." cannot be processed at the receiver, due to a ContractFilter mismatch)


回答1:


IMO, you need to host old services for your previous clients at (preferably) old end points and have new services at new end points. You can take out old services when all your old clients migrate to newer version. Perhaps, you can use inheritance to reduce your efforts, for example

[DataContract(OldNameSpace)]
ClassA {
 ...
}

[DataContract(NewNameSpace)]
ClassB : ClassA {
}

Similarly, create new service contract from inheriting from new one. Service implementation need not change expect it needs to implement new contract. Now you have to configure two end point - one for old contract and another for new contract.

Edit: Put sample interfaces and implementation

Let's say your old contract was something like

public interface IOldContract
{
    ClassA GetFoo();
    void DoBar(ClassA a);
}

Now you can choose the new contract either as

public interface INewContract
{
    ClassB GetFoo();
    void DoBar(ClassB b);
    ClassB GetMix(ClassB a);
}

or as

public interface INewContract2 : IOldContract
{
    ClassB GetFoo2();
    void DoBar2(ClassB b);
    ClassB GetMix2(ClassB b);
}

I tend to go with later variation (as new contract remains compatible with old one). But in your case, you can choose former as you will be anyway exposing two endpoints. Now you need modify service implementation as follows:

    public class ServiceImplementation : INewContract2
{
    #region INewContract2 Members

    public ClassB GetFoo2()
    {
        // Your old implementation goes here 
    }

    public void DoBar2(ClassB b)
    {
        DoBar(b);
    }

    public ClassB GetMix2(ClassB b)
    {
        return GetMixHelper(b);
    }

    #endregion

    #region IOldContract Members

    public ClassA GetFoo()
    {
        return GetFoo2();
    }

    public void DoBar(ClassA a)
    {
        // You old implementation goes here
    }


    public ClassA GetMix(ClassA a)
    {
        return GetMixHelper(a);
    }

    #endregion

    private ClassB GetMixHelper(ClassA a)
    {
        // Your old implementation goes here
    }

}

I hope that you get the idea. Even here also you have multiple choices of code organization. You can have two skeleton service implementation classes - one for old contract and another for new contract. Both will delegate actually functionality to a helper class (which is your current implementation).



来源:https://stackoverflow.com/questions/3519014/wcf-versioning-update-attribute-namespaces-and-support-previous-namespaces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!