Как назвать несколько версий ServiceContracts в одной и той же службе WCF?

Когда вам нужно внести критическое изменение в ServiceContract, рекомендуется сохранить старый и создать новый, а также использовать некоторый идентификатор версии в пространстве имен.

Если я правильно понимаю, то должен сделать следующее:

[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);
}

Благодаря этому я могу создать сервис, который поддерживает обе версии. Это действительно работает, и при тестировании из soapUI выглядит нормально.

Однако, когда я создаю клиент в Visual Studio с помощью «Добавить ссылку на службу», VS игнорирует пространства имен и просто видит два интерфейса с одинаковым именем. Чтобы различать их, VS добавляет «1» к имени одного из них. Я получаю прокси, называемые

ServiceReference.VersionedServiceClient

а также

ServiceReference.VersionedService1Client

Теперь никому не легко увидеть, какая версия новее.

Должен ли я давать интерфейсам разные имена? Например

IVersionedService1
IVersionedService2

or

IVersionedService/2010/01/14
IVersionedService/2010/02/21

Разве это не противоречит цели пространства имен?

Должен ли я поместить их в разные классы обслуживания и получить уникальный URL-адрес для каждой версии?


person Tor Hovland    schedule 26.03.2010    source источник


Ответы (1)


Что ж, как правило, у вас не будет реализации службы, которая одновременно реализует и старый, и новый интерфейс. Поэтому, если появится новый клиент и подключится к вашему новому сервису, он получит только новый интерфейс, и все в порядке.

Если вам нужно иметь возможность предлагать оба интерфейса, тогда да — вам нужно сделать некоторую «магию», чтобы сделать это возможным:

  • если можете, создайте новый интерфейс из старого. Это работает, пока вы добавляете только новые вещи. В новой реализации службы будет реализовываться как интерфейс старого, так и нового стиля.

    public interface IVersionedService2 : IVersionService1
    {
        [OperationContract(Name = "WriteNewGreeting")]
        Greeting WriteNewGreeting(Person2 person);
    }
    

    Таким образом, ваша реализация службы будет иметь как метод WriteGreeting, так и метод WriteNewGreeting — новые клиенты смогут подключаться и использовать любой из них, в то время как более старые клиенты по-прежнему будут видеть свой интерфейс IVersionService1 и «старое» пространство имен и, таким образом, смогут продолжать работу. позвоните в вашу службу

  • если вы не можете получить новую службу из старой, создайте совершенно новую службу и разверните ее на новой конечной точке, например. новый адрес или порт. Таким образом, существующие клиенты могут продолжать вызывать существующую и хорошо известную службу, в то время как новые клиенты могут быть направлены на отдельную службу на отдельной конечной точке, и для них тоже все должно быть хорошо.

person marc_s    schedule 26.03.2010
comment
Спасибо. На самом деле мне не нужно выводить новый интерфейс из старого, чтобы реализовать оба. Мой сервис выполняет общедоступный класс VersionedService: IVersionedService, IVersionedService2, и он отлично работает. Мой вопрос больше о том, нужно ли мне добавлять увеличивающийся номер к интерфейсам, когда я уже использую версионные пространства имен XML? Ваш ответ, кажется, подразумевает, что я должен. - person Tor Hovland; 27.03.2010
comment
@Tor: нет, не обязательно. Если у вас есть один и тот же интерфейс — старый и новый — в двух отдельных пространствах имен XML и выставленный на две отдельные конечные точки (два URL-адреса), тогда клиент всегда будет выбирать один или другой, и у него не будет никаких конфликтов в именовании, я думать. - person marc_s; 27.03.2010