2013-04-23 3 views
9

Я не могу найти пример создания прокси из WSDL с общими типами, но без каких-либо XSD, чтобы идти вместе с ними. Может ли кто-нибудь отметить это как дубликат и указать мне на пример, пожалуйста?Совместное использование типов WSDL без XSD

Здесь 2 услуги, каждая из которых имеет собственное пространство имен и общий тип. Единственное, что доступно для публики, - это их WSDL, XSD или его .dll нет типа для перехода на wsdl.exe /sharedtypes или svcutils, и без него я заканчиваю тем же class Foo, что я не могу пройти до SetFoo и class Foo1.

Лучшее, что я мог придумать генерирует прокси программно и обнаружения дубликатов через CodeDOM, игнорируя DataContract/WebServiceBinding пространств имен, но это огромный беспорядок ...

[WebService(Namespace = "http://tempuri.org/FOO1")] 
public class Service1 : WebService 
{ 
    [WebMethod] 
    public Foo GetFoo() 
    { 
     return new Foo(); 
    } 
} 

[WebService(Namespace = "http://tempuri.org/FOO2")] 
public class Service2 : WebService 
{ 
    [WebMethod] 
    public void SetFoo(Foo foo) 
    { 
    } 
} 

public class Foo 
{ 
    public int Bar { get; set; } 
} 
+0

В качестве определения WSDL определены XSD, определяющие типы. Если они не определены в WSDL, как вы должны использовать эту услугу? –

+0

@hugh Они определены дважды в каждом WSDL, поэтому заданы 'Service1' и' Service2' wsdls. Я не вижу способа генерации прокси для них с общим определением 'Foo', которое может быть передано из' GetFoo' в ' SetFoo'. –

+0

Я понимаю. См. Мой ответ ниже –

ответ

1

Существует способ сделать это, который обозначен here.

В вашем случае вы можете пропустить первый шаг, сгенерировать прокси-сервер из службы 1, а затем использовать флаг/r на svcutil для ссылки на сборку прокси-сервера службы 1 при создании вашего прокси-сервера службы 2.

Это обеспечит, что ваш прокси-сервер службы 2 будет использовать тот же экземпляр Foo из вашего сервиса 1 прокси.

Однако, вы считаете, что просто размещаете одну услугу с двумя операциями? Это сэкономит вам много работы.

Edit: Кроме того, посмотрите на это сообщение: http://blogs.msdn.com/b/youssefm/archive/2009/10/09/reusing-types-in-referenced-assemblies-with-svcutil-s-r-switch.aspx

+0

Кажется не работает, сохраняет 2 'Foo' в 2 разных пространствах имен. Вот настройка (https://github.com/kozhevnikov/WebService1) - «WebService1» с двумя службами: «ClassLibrary1» с общим типом «Foo» и «ConsoleApplication1», который пытается вызвать 'GetFoo' /' SetFoo' через прокси. Я попробовал 'svcutil Service1.wsdl && csc/t: library Service1.cs && svcutil Service2.wsdl/r: Service1.dll' и' svcutil Service1.wsdl/r: .. \ ClassLibrary1 \ bin \ Debug \ ClassLibrary1.dll' но в обоих случаях заканчиваются 2 несовместимыми 'Foo'. –

+0

Можете ли вы опубликовать WSDL, и я посмотрю - возможно, что два Foo действительно являются отдельными типами, определенными в разных XSD, и в этом случае вы не можете использовать флаг/r, потому что типы не являются действительно эквивалентными. –

+0

Точно, они происходят из одного и того же класса, но технически это разные причины. Autogenerated wsdl ставит две копии в двух разных пространствах имен (родительские веб-службы, где они используются), следовательно, вопрос. Пример wsdls находится в https: // github.com/kozhevnikov/WebService1/tree/master/wsdl –

1

Во-первых, вам необходимо установить [DataContract (пространство имен = «некоторое пространство имен здесь»)] для всех типов данных общего обслуживания, в противном случае, когда Создаются WSDL и XSD, тогда у вас будут объекты из двух пространств имен - это абсолютно essential. Значение пространства имен будет применяться только к типам, определенным в XSD, а не к WSDL. XSD = данные, WSDL = служба.

XSD и WSDL и сгенерированы, если и только если у вас установлен набор поведения службы META - добавьте это поведение, а затем вы можете перейти к URL-адресу. URL-адрес поведения службы META будет иметь ссылку на ваши WSDL и XSD.

Я использую следующий фрагмент кода для услуг собственной хостинга в службах Windows, а не через IIS, однако применяются те же принципы ....

/// <summary> 
/// Enables meta data output for a service host. 
/// </summary> 
/// <param name="host">The service host.</param> 
/// <remarks>Must be invoked prior to starting the service host.</remarks> 
public static void SetupMetaDataBehaviour(ServiceHost host) 
{ 
    ServiceMetadataBehavior metaDataBehaviour = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
    if (metaDataBehaviour == null) 
    { 
     metaDataBehaviour = new ServiceMetadataBehavior(); 
     metaDataBehaviour.HttpGetEnabled = true; 
     host.Description.Behaviors.Add(metaDataBehaviour); 
    } 
    else 
    { 
     metaDataBehaviour.HttpGetEnabled = true; 
    } 
} 
+0

Спасибо, но в соответствии с OP я не могу изменять службы или типы, у меня есть доступ к необработанным автогенерированным WSDL, как если бы они были общедоступными (технически я отразил типы, из которых я сам создаю WSDL), сервисы имеют уникальное [WebService (пространство имен]] на них, а типы не имеют на них ничего, кроме случайных XmlInclude, никаких атрибутов, связанных с сервисом или пространством имен. –

+0

Как и в примере 'GetFoo' /' SetFoo', у меня есть WSDL для 'Service1' и' Service2', и мне нужно создать прокси для них с общим 'Foo', поэтому я могу вызвать' GetFoo' и передать его 'SetFoo' 'под другим автогенерированным пространством имен (работает, когда я возится с' CodeDOM', извлекаю 'Foo' и удаляю любые пространства имен, но этот подход не масштабируется до сотен неясных устаревших веб-сервисов). –

1

После добавления двух веб-ссылки:

  1. двойной щелчок по ссылке
  2. второй веб-службы в обозревателе объектов перейдите к определению Foo
  3. правой кнопкой мыши на Foo и выберите перейти к определению
  4. удалить определение для класса Foo
  5. Добавить инструкцию using для пространства имен веб-сайтов один
  6. е р в
  7. найти и заменить все экземпляры <namespace-of-service-reference-2>.Foo только с Foo

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

+1

Спасибо, но это то же самое, что и после генерации CodeDOM-манипуляций, только вручную. Я ищу способ сделать это автоматически или программно (например, CodeDOM) и масштабируемым до сотен или устаревших веб-сервисов с тысячами разделяемых типов. –

+0

Я понимаю, что вы хотите сделать. Но так как visual studio автоматически генерирует два класса в разных пространствах имен, используя только файл wsdl, вы не получите этого. Мое решение занимает около 5 минут, чтобы внести изменения в большой проект. Его повторяемость и легко запоминается. –

+0

Кроме того, это не общий сценарий. особенно в среде с «сотнями или устаревшими веб-службами», вы можете столкнуться с этой проблемой один раз, используя один сторонний API из сотен. Если это внутренний код, не записывайте его таким образом. Если вы не являетесь лицом, вызывающим выстрелы, и кто-то архивирует службы таким образом, вам нужно сесть и показать им уровень разочарования, которое вызывает этот дизайн. –

Смежные вопросы