Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Работа с Web service'ом через С++


Автор: Brodyaga 12.11.2008, 08:13
Всем доброго времени суток! Есть WebService работающий на C#.. Подскажите пожалуйста, как  мне использовать его через C++ :

Автор: Brodyaga 12.11.2008, 18:05
Покопал немного под это дело... Это нужно через протокол SOAP с ним общаца... Кто-нибудь знает есть ли какиенить стандартные средства в си для взаимодействия с SOAP?? не в ручную же xml составлять....

Автор: Fazil6 12.11.2008, 18:23
Цитата(Brodyaga @  12.11.2008,  18:05 Найти цитируемый пост)
не в ручную же xml составлять.... 

составлять xml вручную особой проблемой не является.

набери в MSDN
ATL SOAP
получишь кучу документации с примерами

Автор: Vyacheslav 12.11.2008, 18:25
http://gsoap2.sourceforge.net/
Все элементарно и просто.
Имел опыт разработки клиента под WebService (C#) для Windows и Linux

Автор: Brodyaga 13.11.2008, 08:00
Vyacheslav, можете примерчик скинуть простейшего обращения к сервису, вызова метода и получения от него ответа с использованием gsoap?

Автор: Brodyaga 13.11.2008, 15:31
Нашёл в инете несколько способов работы с Soap через C++.. Выбрал способ через библиотеку MSSOAP1.dll . Столкнулся с проблемой передачи функции параметра.
Код

#import "C:\\Program Files\\Common Files\\MSSoap\\Binaries\\MSSOAP1.dll" named_guids raw_interfaces_only exclude("IStream","ISequentialStream","_LARGE_INTEGER","_ULARGE_INTEGER","tagSTATSTG","_FILETIME")
#import "C:\\Program Files\\Common Files\\MSSoap\\Binaries\\WiSC10.dll" raw_interfaces_only exclude("IStream","ISequentialStream","_LARGE_INTEGER","_ULARGE_INTEGER","tagSTATSTG","_FILETIME")

using namespace MSSOAPLib;


    ISoapSerializerPtr Serializer;
    ISoapReaderPtr Reader;
    ISoapConnectorPtr Connector;
    IStream *inputstream=NULL;
    IStream *outputstream=NULL;

    BSTR endpoint = L"EndPointURL";
    BSTR action = L"SoapAction";
    _variant_t vEndPoint = <адрес сервиса>;
    _variant_t vAction = <путь к функции>;

    BSTR method = <имя функции>;
    BSTR command = <путь к функции>;
    BSTR m = L"m";
    BSTR a = L"param";

        Connector = NULL;

        Connector.CreateInstance(__uuidof(HttpConnector));

        Connector->put_Property(endpoint,vEndPoint);
        Connector->Connect();

        Connector->put_Property(action,vAction);
        Connector->BeginMessage();

        Serializer = NULL;
        Serializer.CreateInstance(__uuidof(SoapSerializer));

        Connector->get_InputStream(&inputstream);

        Serializer->Init(stream);

        Serializer->startEnvelope(NULL,NULL,NULL);
        Serializer->startBody(NULL);
        Serializer->startElement(method,command,NULL,m);
        Serializer->startElement(a,NULL,NULL,NULL);
        Serializer->writeString(L"abcdef");
        Serializer->endElement();
        Serializer->endElement();
        Serializer->endBody();
        Serializer->endEnvelope();

        Connector->EndMessage();

        Reader = NULL;
        Reader.CreateInstance(__uuidof(SoapReader));

        Connector->get_OutputStream(&outputstream);

        VARIANT_BOOL bres;

        IXMLDOMElement *element;

        VARIANT_BOOL* var_bool=new VARIANT_BOOL(VARIANT_FALSE);
        Reader->Load(_variant_t((IUnknown*)outputstream),L"SoapAction",var_bool);
        Reader->get_RPCResult(&element);
        BSTR buff;
        element->get_baseName(&buff);
        cout << W2A(buff) << endl;
        element->get_text(&buff);
        cout << W2A(buff) << endl;

        Reader = NULL;
        Serializer = NULL;
        Connector = NULL;


Функция специально была создана для тестов на сервисе написанном на C#. Принимает строку типа string и возвращает строку типа string. Но в данном случае она вообще не возвращает объект element... Пробовал с аналогичной функцией, но принимающей параметр типа long.  С ней этот код работает...
Тоесть получается что не работает только с функцией принимающей String... Помогите пожалуйста кто реализовывал чтонить подобное... Как передать через SOAP веб сервису в функцию параметр типа String ???


Автор: Lycifer 14.11.2008, 11:01
Если у тебя window то поможе ком объект(я не помню как класс называется, он умеет загружать збокри DotNet вот только не строгая сигнатура...)

Если ты романтик + к этому хочеш добится великой совместности сокеты помогут , но вот только "секса будет много " - что бы подержать самому Web Service.

Есть еще вариант что вызывай через C# а управление передовай в С++ (.Net call native code).

Самый легкий способ это использовать С++ Manager(но примоложение больше по размерам и какое то не то, в отличии от C#, хотя считается лучше поддержка С++ unmanager, кажется Manager был зделан для этого) 


Это все, пиши есчё)))))))))))))

Автор: Brodyaga 14.11.2008, 11:21
Покопал глубже и понял что косяк в том, что параметры в методы вызывемые на веб сервисе вообще не передаюца!!!
Использую тот же код, параметр в нём передаёца вот здесь... :
Код

        Serializer->startElement(a,NULL,NULL,NULL);
        Serializer->writeString(L"abcdef");
        Serializer->endElement();


Вот код метода который принимает параметр на веб сервисе:
Код

    public int HelloWorld(string a) 
    {
        return "Hello World";
    }


вообщем a = null, хотя параметр то я передаю!! И имя у него такое же указываю, тобишь "a"...
Если сделать функцию принимающую параметры типа int, то будет тоже самое, принимаемое значение будет равно 0. Тоесть чтобы я ни передавал, в функцию на сервис параметры не доходят... Подскажите в чём дело кто знает, плиз?? :(

Автор: jonie 16.11.2008, 14:38
http://www.rsdn.ru/article/xml/soapatl.xml
http://www.rsdn.ru/article/xml/soap.xml

почитайте

Автор: Brodyaga 17.11.2008, 01:16
Прочитал.. но не нашёл где там сказано про использование MSSOAP1.dll.. Меня интересует почему проблема в коде, который приводят в различных примерах как работающий, а на деле он не работает...

Автор: Brodyaga 17.11.2008, 11:43
Вообщем так... сделал обращение к веб-сервису своему, через Builder. Та же проблема....
Нашёл одну ооочень интересную http://www.sql.ru/forum/actualthread.aspx?bid=20&tid=351681&pg=1...

Там у человека та же проблема, но при работе с веб-сервисом через Delphi...

Там проблема решилась добалением строчки:
Код

InvRegistry.RegisterInvokeOptions(TypeInfo(AuthServiceSoap), ioDocument);


Добавил в проекте билдеровском аналогичную строку:
Код

InvRegistry()->RegisterInvokeOptions(__interfaceTypeinfo(FirstServiceSoap),ioDocument);

И всё заработало...

Прочитал гдето, что эта строчка, переключает использование по умолчанию rpc на soap... 
Что то типа того... Но мне надо всё это провернуть на MSVC 2005... Как мне сделать
аналогичную вещь в студии?

Привожу на всякий случай запрос от билдера после добавления заветной строчки smile :
Код

POST /MyService/Service.asmx HTTP/1.1
Accept: text/xml
SOAPAction: "http://tempuri.org/HelloWorld"
Content-Type: text/xml
User-Agent: Borland SOAP 1.1
Host: 62.165.44.152:80
Content-Length: 327
Proxy-Connection: Keep-Alive
Pragma: no-cache

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance"><SOAP-ENV:Body><HelloWorld xmlns="http://tempuri.org/">
<a>23</a></HelloWorld></SOAP-ENV:Body></SOAP-ENV:Envelope>


Неужели никто не сталкивался с такой проблемой?! не верю! smile даже на зарубежном
форуме одном нашёл сообщения с такой же проблемой от 2006 г., правда там тоже никто
не ответил... ;)

Подскажите плиз как всётаки с библиотекой MSSOAP1.dll совладать... 

Кстати... Нашёл ещё одну библиотечку... вот http://www.codeproject.com/KB/COM/xysoapclient.aspx?display=PrintAll&fid=13980&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26
Но она тоже не работает, тут уж совсем.. даже объект почемуто по CreateInstance не
создаётся, тоесть вот здесь уже косяк:
Код

pSoapClient.CreateInstance( __uuidof(XYSoapClient));

pSoapClient остаётся равным null...

вот кстати http://www.codeproject.com/KB/XML/vcsoapclient.aspx на пример,
который за основу взял я... и в котором соответственно нужно что-то поправить аналогичное исправленному в билдере...

Ну что форумчане... жду ваших высказываний и помощи...

Автор: jonie 17.11.2008, 22:28
Цитата

Кстати... Нашёл ещё одну библиотечку... вот ссылка
Но она тоже не работает, тут уж совсем.. даже объект почемуто по CreateInstance не
создаётся

Цитата

You also need to install Microsoft SOAP Toolkit 3.0 (or 2.0).
условие выполнено ? библиотека зарегина ?

Автор: Brodyaga 18.11.2008, 08:12
Цитата

условие выполнено ? библиотека зарегина ?

зарегина имеется ввиду утилитой regsrv ?

Автор: Vyacheslav 18.11.2008, 17:08
Цитата(Brodyaga @  13.11.2008,  08:00 Найти цитируемый пост)
Vyacheslav, можете примерчик скинуть простейшего обращения к сервису, вызова метода и получения от него ответа с использованием gsoap? 

Поздно, наверное, но отвечу.
Вы по всей видимости даже не смотрели, потому  как там все просто.
А сам примерчик ничего Вам не даст., потому как там есть утилита которая на основе wsdl генерит  код прохи

Код

void UploadImage( std::string filePath, ImageID& imageID  )
{
    MyServiceSoap service;
    if( END_POINT ) {
        service.endpoint = END_POINT; 
    }
    _ns1__UploadImage request;
    _ns1__UploadImageResponse response;
    request.file = &filePath;
    if(service.__ns1__UploadImage(&request,&response) == SOAP_OK) {
         imageID = *(response.UploadImageResult);
         return;        
    } 
    throw ServiceError( service );
}

void ApplyFilter(ImageID source, std::string params, ImageID& target ) throw(ACDException)
{
    _ns1__ApplyFilter request;
    _ns1__ApplyFilterResponse response;
    request.file = &source;
    request.filterParams = &params;
    if(m_service->__ns1__ApplyFilter(&request,&response) == SOAP_OK) {
         target = *(response.ApplyFilterResult);     
         return;        
    } 
    throw ServiceError( *m_service );
}


 

использование
Код


UploadImage(args[FileUrl], result ); 

... 
                    ifstream file(args[Params].c_str());
                    
                    if (!file.is_open()) {
                        errorStream  << "Error: Can't open Parameter file : " << args[Params];
                        throw exception(string(errorStream.str(),errorStream.pcount()).c_str());        
                    }
                    istreambuf_iterator<char> iterator(file);
                    string params(iterator, istreambuf_iterator<char>());
                    ApplyFilter(args[FileUrl], params, result);






Автор: Brodyaga 19.11.2008, 08:31
Цитата

условие выполнено ? библиотека зарегина ?


Да, действително... зарегал, видать выдало какуюто ошибку, а я посчитал что всё ок... библиотека действительно не была зарегана. Сейчас зарегал по новой... теперь класс не правильно инициализируется. Вот тут функция InitService возвращает 0 :
Код

_bstr_t sWSDL = L"http://localhost:1520/WebSite1/Service.asmx?wsdl";

long l=pSoapClient->InitService(sWSDL, sEmpty, sEmpty, sEmpty);


В чём сейчас проблема? кто знает?

Автор: Brodyaga 22.11.2008, 16:18
Ну что никто не знает? подскажите ктонить, сильно надо :(

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)