Поиск Web-сервисов — DISCO
Если у клиента имеется WSDL-контракт, описывающий Web-сервис, то у него есть вся информация для вызова этого Web-сервиса. Но после того, как вы сделали Web-сервис доступным, развернув его на Web-сервере, откуда клиенты возьмут WSDL-контракт? Более того, откуда клиенты вообще узнают о существовании вашего Web-сервиса?
Ответ состоит из двух частей: DISCO и UDDI (Universal Description, Discovery and Integration). Первый - это файловый механизм поиска локальных Web-сервисов, т.е. механизм получения списка доступных Web-сервисов из DISCO-файлов, размещенных на Web-серверах. Второй — это глобальный справочник Web-сервисов, который сам реализован как Web-сервис.
DISCO (сокращение от «discovery») – это простой протокол, работающий с DISCO-файлами в формате XML Основная идея в том, что вы на своем Web-сервере публикуете DISCO-файл, описывающий Web-сервисы, доступные на данном и, возможно, на других серверах. Клиенты могут обращаться к содержимому DISCO-файлов и отыскивать там сведения о том, какие Web-сервисы доступны и где находятся их WSDL-контракты. Например, вы создали два Web-сервиса с такими URL:
- http://www.wintellect.com/calc.asmx;
- http://www.wintellect.com/locator.asmx.
Чтобы объявить об их существовании, вы можете разместить следующий DISCO-файл по стандартному адресу на своем сервере. Элементы contractRef задают URL для WSDL-контрактов. URL могут быть абсолютными или относительными (относительно каталога, в котором находится DISCO-файл). Необязательные атрибуты docRef задают расположение документов, описывающих Web-сервисы, которые в связи с самодокументирующейся природой Web-сервисов, разработанных с помощью .NET Framework, обычно сами являются ASMX-файлами:
<?xml version="1.0" ?><discovery xmlns="http://schemas.xmlsoap.org/disco/" xmlns:scl="http://schemas.xmlsoap.org/disco/scl/"> <scl:contractRef ref="http://www.wintellect.com/calc.asmx?wsdl" docRef="http://www.wintellect.com/Calc.asmx" /> <scl:contractRef ref="http://www.wintellect.com/locator.asmx?wsdl" docRef="http://www.wintellect.com/Locator.asmx" /></discovery>При желании можно писать отдельные DISCO-файлы для каждого Web-сервиса и помещать ссылки на них в главный DISCO-файл с помощью элементов discoveryRef. Вот пример DISCO-файла, ссылающегося на другие DISCO-файлы. Здесь URL также могут быть абсолютными или относительными:
<?xml version="1.0" ?><discovery xmlns="http://schemas.xmlsoap.org/disco/"> <discoveryRef ref="http://www.wintellect.com/calc.disco" /> <discoveryRef ref="http://www.wintellect.com/locator.disco" /></discovery>Третий вариант — разместить VSDISCO-файл и использовать динамический поиск (dynamic discovery). Следующий VSDISCO-файл автоматически публикует все ASMX- и DISCO-файлы в данном каталоге и его подкаталогах, кроме подкаталогов, указанных элементами exclude.
Как работает динамический поиск? ASP.NET отображает расширение имени файла .vsdisco на HTTP-обработчик, который отыскивает в данном каталоге и его подкаталогах файлы ASMX и DISCO и возвращает динамически генерируемый DISCO-документ. Клиент,обращающийся к VSDISCO-файлу, получает в ответ нечто, похожее на статический DISCO-файл.
По соображениям безопасности Microsoft отключила динамический поиск прямо перед выходом .NET Framework версии 1.0. Вы можете снова включить его, раскомментировав строку в разделе httpHandlers файла Machine.config, которая связывает .vsdisco с SystemWebSewicesDiscoveiyDiscoveryRequestHandler, и предоставив учетной записи ASPNET право доступа к метабазе IIS.
Чтобы еще больше упростить поиск Web-сервисов, вы можете поместить в домашний HTML-документ своего сайта ссылку на главный DISCO-файл. Допустим, например, что таким документом на www.wintellect.com является Default.htmlи в том же каталоге находится DISCO-документ Default.disco. Добавление следующего фрагмента в Dcfault.html позволит большинству инструментов, работающих с DISCO-файлами, принимать URL www.wintellect.com (в противоположность с www.wintellect.com/default.disco):
<html> <head> <link type="text/html" rel="alternate" href="Default.disco"> </head></html>Visual Studio .NET ( а именно команда Add Web Reference) работает с DISCO-файлами, как и утилита Disco.exe из-NET Framework SDK.
Основной недостаток DISCO в том, что вы не можете считать DISCO-файл, если не знаете его URL. Так как же найти Web-сервис, если мы не знаем даже URL, с которого можно было бы начать? - U-D-D-I (ю-ди-ди-ай).
Поиск Web-сервисов — UDDI
UDDI — это сокращение от «Universal Description, Discovery, and Integration» («Универсальное описание, поиск и интеграция»). Разработанная совместно IBM, Microsoft и Ariba и поддерживаемая сотнями других компаний, она представляет собой спецификацию построения распределенных БД, которая позволяет отыскивать Web-сервисы. Эти БД никому не принадлежат, и каждый может опубликовать собственный реестр на основе UDDI. Сайты-операторы, уже организованные IBM и Microsoft, вероятно, будут первыми из множества подобных сайтов, которые появятся в будущем.
UDDI-сайты и сами являются Web-сервисами, Они предоставляет пару API на основе SOAP: API запросов для получения информации о компаниях и их Web-сервисах, а также API публикаций для объявления о доступности Web-сервисов компании. API запросов может использовать каждый, но к API публикаций сайты-операторы обычно позволяют обращаться только зарегистрированным членам. Сведения об этих API и другую информацию о UDDI см. по адресу http://www.uddi.org. Большинство разработчиков никогда не будет использовать API UDDI напрямую. Вместо этого для обращения к реестрам UDDI и генерации классов-оболочек для вызова найденных там Web-сервисов они будут применять инструменты высокого уровня, такие как Visual Studio .NET. Фактически непосредственно вызывать UDDI будут только разработчики инструментария, а также клиенты, которым нужно отыскивать Web-сервисы и подключаться к ним динамически.
Клиенты Web-сервисов
Теперь, когда мы подробно познакомились с Web-сервисами, пора заняться их клиентами, т. е. приложениями, которые используют или потребляют Web-методы. Web-сервисы писать легко. Написание их клиентов еще проще, благодаря наличию соответствующей высокоуровневой поддержки в библиотеке FCL и генератору кода Wsdl.exe. При наличии у вас WSDL-контракта, описывающего Web-сервис (или URL DISCO-файла, ссылающегося на WSDL-контракт), вы сможете вызывать его практически сразу.
Прокси Web-сервисов
Основная концепция, с которой нужно быть знакомым для написания клиентов Web-серисов, — это прокси Web-сервиса. Прокси Web-сервиса — это объект, который является локальным представлением удаленного Web-сервиса. Экземпляр прокси создается в домене приложения клиента, но вызовы прокси передаются последним Web-сервису, который он представляет. Утилита Wsdl.exe, поставляемая в составе .NET Framework SDK (и интегрированная в Visual Studio .NET), генерирует прокси-классы Web-сервисов на основе WSDL-контрактов. После создания прокси вызов соответствующего Web-сервиса — это просто вызов методов прокси:
CalculatorWebService calc = new CalculatorWebService ();Int sum = calc.Add(2,2);Методы прокси-класса соответствуют Web-методам Web-сервиса. Если Web-сервис предоставляет методы Add и Subtract, то и его прокси также содержит их. При вызове любого из этих методов прокси упаковывает входные параметры и вызывает Web-метод, по протоколу, инкапсулированному в прокси (обычно это SOAP). Прокси изолирует вас от низкоуровневых деталей Web-сервиса и используемых им протоколов. Он даже выполняет разбор XML, возвращенного Web-сервисом, и преобразует результаты в управляемые типы данных.
Сгенерировать прокси Web-сервиса с помощью Wsdl.exe очень просто. Допустим, нужно вызвать Web-сервис, URL которого http://www.wintenect.com/calc.asmx. Если Web-сервис написан с помощью .NET Framework, т. е. WSDL-контракт можно получить, добавив строку запроса «?wsdl» к URL сервиса, то сгенерировать прокси для этого сервиса можно так:
wsdl http://www.wintellect.com/calc.asmx?wsdl
Или вы можете опустить строку запроса, и Wsdl.exe подставит ее за вас:
wsdl http://www.wintellect.com/calc.asmx
Если при написании Calc.asmx .NET Framework не использовалась, то он может и не поддерживать строки запроса WSDL. Тогда вам нужно самому отыскать WSDL-контракт и передать Wsdl.exe его URL (или локальное путевое имя). В следующем примере предполагается, что контракт находится в локальном файле Calc.wsdb
Wsdl calc.wsdl
Независимо от способа указания WSDL-контракта, Wsdl.exe генерирует CS-файл, содержащий класс, представляющий собой прокси Web-сервиса. Экземпляр именно этого класса вы должны создать для вызова методов Web-сервиса.
Имя класса образуется по имени сервиса (т. е. по атрибуту пате элемента service) в WSDL-контракте. Например, допустим, что в файле ASMX Web-сервиса содержится атрибут:
[WebService (Name="Calculator Web Service")]
В результате WSDL-контракт будет содержать тэг:
<service name="Calculator Web Service">
а именем класса прокси будет CalculatorWebService. По умолчанию имя CS-файла, который генерирует Wsdl.exe, также получается из имени сервиса (например, Calculator Web Service.cs). Вы можете задать другое имя через параметр /out командной строки Wsdl.exe. Команда:
wsdl /out: Calc.cs http://www.wintellect.com/calc.asmx
генерирует файл Calc.cs независимо от имени сервиса.
Wsdl.exe поддерживает много параметров командной строки, с помощью которых вы можете влиять на результаты ее работы. Так, если вы хотите, чтобы класс прокси был не на С#, а не Visual Basic .NET, задайте параметр /language.
wsdl /language:vb http://www.wintellect.com/calc.asmx
Если нужно, чтобы Wsdl.exe поместил генерируемый им код в пространство имен (это очень полезная возможность для предотвращения коллизии имен между типами в сгенерированном коде и типами, определенными в вашем приложении или в FCL), определите параметр /namespace-.
wsdl /namespace:Calc http://www.wintellect.com/calc.asmx
Wsdl.exe генерирует классы, производные от базовых классов из пространства имен FCL SystemWebServicesProtocols. По умолчанию базовым для класса прокси будет SoapHttpCHentProtocol, который позволяет использовать для вызова Web-методов SOAP поверх HTTP. Параметр командной строки /protocol позволяет задать другой протокол вызова. Команда:
wsdl /protocol:httpget http://www.wintellect.com/calc.asmx
создает прокси, являющийся производным от HttpGetCHentProtocol и вызывающий Web-методы с помощью HTTP-команд GET, тогда как команда:
wsdl /protocol:httppost http://www.wintellect.com/calc.asmx
создает прокси, являющийся производным от HttpPostCtientProtocol и вызывающий Web-методы с помощью HTTP POST. Зачем изменять протокол, используемый классом прокси для вызова Web-методов? Обычно SOAP прекрасно подходит. Если же вызываемые вами методы – это простые методы, использующие столь же простые типы, то HTTP GET или POST немного повышают эффективность вызовов за счет сокращения объема данных, пересылаемых по сети.
Кстати, если вы пишете клиенты Web-сервисов с помощью Visual Studio .NET, запускать Wsdl.exe вручную не нужно. При вызове команды Add Web Reference, расположенной в меню Project (в среде Visual Studio 2003) или Website (в среде Visual Studio 2005), Visual Studio .NET запускает Wsdl.exe автоматически и добавляет класс прокси в ваш проект. Add Web Reference также понимает UDDI, что позволяет легко отыскивать нужные Web-сервисы в UDDI-реестре Microsoft.