Показаны сообщения с ярлыком WSDL. Показать все сообщения
Показаны сообщения с ярлыком WSDL. Показать все сообщения

суббота, 11 апреля 2009 г.

Простой пример клиента для WebService

Одному моему коллеге понадобилось написать небольшого клиента для сервера контента системы электронного документооборота. Собственно сам сервер контента реализован в виде WEB-сервиса, предоставляющего некоторые функции для доступа к документам. Что он только не пробовал и ClientSocket и TCPConnection и HTTPRIO. Но на самом деле все достаточно просто, и не нужно изобретать велосипед :)

Сразу же оговорюсь , что данный пост не претендует на полноту изложения данной темы, здесь я просто хочу показать в каком направлении следует «копать» и покажу как обойти один подводный камень, на который можно наткнуться при создании клиента для WEB-сервисов.

Итак, приступим … У нас есть некоторый WEB-сервис, предоставляющий некоторые функции. Пусть это будет некоторый ASP.NET WebService запущенный на соседней машине с именем Athlon, URI данного WEB-сервиса выглядит следующим образом: http://athlon/test/service.asmx . Набрав данный URI в браузере получаем тестовую страничку, сгенерированную IIS для проверки работоспособности WEB-сервиса:


Из тестовой страницы видно, что WEB-сервис поддерживает одну единственную процедуру с именем HelloWorld. Попробуем ее вызвать из клиентского приложения на Delphi. Естественно создадим новый проект, сохраним куда-нибудь по-удобнее, и займемся самым интересным – автоматической генерацией кода для доступа к WEB-сервису. Для этого в среде Delphi есть специальный мастер который вызвается следующей командой: File -> New -> Other … -> WebServices -> WSDL Importer:



В мастер вводится один единственный параметр – это URI нашего WEB-сервиса:



Но при попытке перейти на следующий шаг мастера появится сообщение об ошибке, примерно следующего содержания, толком ничего не говорящего:



Давайте разберемся, что это такое и почему это происходит. Еще раз наберем URI WEB-сервиса в строке адреса браузера – на экране отобразится тестовая страничка. Тоже самое происходит когда по данному URI обращается мастер – в соответствии с протоколом SOAP он ждет XML описания WEB-сервиса, а ему вместо этого выдают обычную html-страницу. Именно по этому он вываливается с ошибкой невразумительного содержания, поскольку пытается разобрать html и ему это не удается и он сообщает на каких именно тэгах разметки он вы вывалился. Чтобы этого не происходило, мы должны явно указать WEB-сервису, что мы ждем от него WSDL описание сервиса. Делается это очень просто, просто добавляется параметр ?WSDL в URI WEB-сервиса:


http://athlon/test/service.asmx?WSDL



Теперь мастер получает именно те данные, которые ожидает и генерация кода происходит без ошибок:



В результате сгенерировался довольно большой код, ключевой фрагмент которого выглядит так:


  ServiceSoap = interface(IInvokable)
['{77573149-9C57-FA51-F11F-EFD527C91BD9}']
function HelloWorld: string; stdcall;
end;

function GetServiceSoap(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): ServiceSoap;

Здесь объявляется интерфейс нашего WEB-сервиса и функция для получения этого интерфейса, именно с ними мы и будем дальше работать. Просто для примера вызовем в обаботчике события OnClick для кнопки процедуру и выведем сообщение с результатом


procedure TForm1.Button1Click(Sender: TObject);
var
ws: ServiceSoap;
begin
// получаем интерфейс
ws := GetServiceSoap();
// вызываем процедуру сервиса
with ws do
ShowMessage(HelloWorld);
end;

Вот собственно и все - клиент для WEB-сервиса готов. На его создание потрачено совсем немного времени и написано совсем небольшое количество кода.