Click here to Skip to main content
Click here to Skip to main content

C++ SOAP client for MS SOAP Toolkit 1.0 using wire transfer technique

By , 7 Feb 2001
 
  • Download source files - 2 Kb
  • Download demo project - 62 Kb
  • Requirements

  • SOAP Toolkit Version 1.0 - December 2000 Release
  • Microsoft XML Parser (Part of IE5 or later)
  • Introduction

    In July 2000, Microsoft released the first version of the SOAP Toolkit for Visual Studio 6.0. In September 2000 the Beta 1 of the SOAP Toolkit Version 1.0 was release. In my opinion the most remarkable feature that was added is the SSL support. The most recent, non beta version is the version from December 2000 with bug fixes and small changes in the exposed interfaces. The purpose of this article is to demonstrate the wire transfer technique using a C++ client and ATL. Many thanks to Peter Santos.

    About sample

    MS provided, for testing purposes, the web service. The web service description can be found at the following link. The sample use this web service and demonstrates the execution of GetStockQuote method exposed by this web service. The sample contain two methods Connect and GetStockMethod.

    Connect method

    This is the method for obtaining the service description and URI listener from the web service. These are two strings (BSTRs) that we will keep for using in GetStockMethod

    	long            nSuccess, item = 0;
    	CComVariant     varTemp;
    
    	ROPE::ISOAPPackagerPtr          packer;
    	CComPtr<IUnknown>               pIUnknown;
    	ROPE::IServiceDescriptorsPtr    pIServiceDescriptors;
    	ROPE::ISDEndPointInfoPtr        pISDEndPointInfo;
    	USES_CONVERSION;
    
    	try
    	{
    		
    		HRESULT hr = packer.CreateInstance( ROPE::CLSID_SOAPPackager );
    		
    		//load service description from this web service
    		hr = packer->LoadServicesDescription(ROPE::icURI, 
    							bstrLocation, NULL, &nSuccess);
    		if( nSuccess != 1 )
    			throw E_FAIL;
    
    		//get service descriptors
    		hr = packer->get_GetServiceDescriptors(ROPE::icENDPOINTINFO, &varTemp);
    
    		pIUnknown.Attach( varTemp.pdispVal );
    		pIUnknown.QueryInterface( &pIServiceDescriptors );
    		
    		//get first descriptor on the list
    		VariantInit(&varTemp);
    		hr = pIServiceDescriptors->get_Item(variant_t(item),&varTemp);
    		pIUnknown.Detach();
    
    		//get the endpoint(URI address) a.e. where the SOAP message will be sent
    		pIUnknown.Attach( varTemp.pdispVal );
    		hr = pIUnknown.QueryInterface( &pISDEndPointInfo );
    		hr = pISDEndPointInfo->get_URI(&URI_LISTENER);
    		
    		//get the service description
    		hr = packer->get_ServicesDescription(&bstrSrvDesc);
    	}
    	catch(...)
    	{
    		std::cout << "Connection failure ! "<< std::endl;
    		return false;
    	}
    	std::cout << "Connection successfull "<< std::endl;
    	return true;

    GetStockMethod

    This is the method for calling the exposed GetStockPrice method from the web service. After the creation of a new SOAPPackager object and the loading of the service description from the string obtained from the Connect method, the payload will be created and posted (using a new WireTransfer object)to the web service and the result will be displayed

    	long		nSuccess;
    	CComBSTR	bstrRequestStruct, bstrRequestPayload, bstrResponsePayload;
    	CComVAriant varPrice;
    	
    	ROPE::ISOAPPackagerPtr packer;
    	ROPE::IWireTransferPtr wireTrans;
    
    	USES_CONVERSION;
    
    	try
    	{
    		HRESULT hr = packer.CreateInstance( ROPE::CLSID_SOAPPackager );
    
    		//load service description using the string from previous Connect method call
    		hr = packer->LoadServicesDescription(ROPE::icSTRING, 
    							bstrSrvDesc, NULL, &nSuccess);
    		if( nSuccess != 1 )
    			throw E_FAIL;
    		
    		//seek in the service description 
    		//the method structure a.e. what we need to call this method
    		hr = packer->GetMethodStruct(CComBSTR("GetStockQuote"), ROPE::icINPUT, &bstrRequestStruct);
    		
    		// set method name 
    		hr = packer->SetPayloadData(ROPE::icREQUEST, CComBSTR(""), CComBSTR("GetStockQuote"), bstrRequestStruct); 
    
    		//set method parameters
    		hr = packer->SetParameter(  ROPE::icREQUEST, CComBSTR("Symbol"), CComVariant("MSFT") );
    		hr = packer->SetParameter(  ROPE::icREQUEST, CComBSTR("description"), CComVariant("any company") );
    
    		//get the data that will be sended to web server( payload ) 
    		hr = packer->GetPayload( ROPE::icREQUEST, &bstrRequestPayload);
    
    		std::cout <<  W2A(bstrRequestPayload) << std::endl << std::endl;
    		
    		//post the payload
    		wireTrans.CreateInstance( ROPE::CLSID_WireTransfer);
    		hr = wireTrans->AddStdSOAPHeaders(URI_LISTENER,CComBSTR("GetStockQuote"),bstrRequestPayload.Length());
    		hr = wireTrans->PostDataToURI(URI_LISTENER, bstrRequestPayload, &bstrResponsePayload);
    
    		std::cout <<  W2A(bstrResponsePayload) << std::endl << std::endl;
    
    		//this is the response from service 
    		hr = packer->SetPayload( ROPE::icRESPONSE, bstrResponsePayload);
    		
    		//get return value
    		hr = packer->GetParameter( ROPE::icRESPONSE, CComBSTR("result"), &varPrice);
    		std::cout << W2A(varPrice.bstrVal) << std::endl;
    	}
    	catch(...)
    	{
    		std::cout << "Something wrong happened !" << std::endl<< std::endl;
    	}

    Conclusions

    I hope you will find this approach useful.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    About the Author

    Catalin Hatmanu
    Software Developer (Senior) binaryfog.com
    Canada Canada
    Member

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    QuestionSOAP response is ?memberILoveMJ18 Dec '06 - 2:55 
    have developed a soap client using the high level interface and its working fine when i use webservices which return only one string back but if the webservice is returnning more than one complex data type it shows the result as "??????"
    here is my code where i call the webservice and process the response.
     
    hr = m_pSoapClient->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, &result, &ExceptInfo, NULL);
     
    if(FAILED(hr))
    {
    DisplayFault(_T("Invoke of method failed."));
    }
    else
    {
    VariantChangeType(&result, &result, 0, VT_BSTR);//line to be checked
    // Display result.
    // m_ResultCtl.SetWindowText(CString(result.bstrVal));
    ::MessageBox(NULL,CString(result.bstrVal),"HII",MB_OK);
    }
    QuestionHELP ME!!!why toolkit3.0 generate these bad XML for me?membergxulg16 Jan '05 - 19:08 
    Hi, i have installed MS SOAP Toolkit3.0, the platform is WINDOWSXP+SP2, the code i wirte is listed below:
    #include <stdio.h>
    #import "msxml4.dll"
    using namespace MSXML2;
    #import "C:\Program Files\Common Files\MSSoap\Binaries\mssoap30.dll" \
                      exclude("IStream", "IErrorInfo", "ISequentialStream", "_LARGE_INTEGER", \
                                  "_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")
     
    using namespace MSSOAPLib30;
    void Get()
    {
          HRESULT hr;
         
          ISoapSerializerPtr Serializer;
          ISoapReaderPtr Reader;
          ISoapConnectorPtr Connector;
          // Connect to the service.
          hr = Connector.CreateInstance(__uuidof(HttpConnector30));
          Connector->Property["EndPointURL"] = L"http://update.waytech.com.cn/Webservices/WTAU/WTAU.asmx?WSDL";
          hr = Connector->Connect();
         
          // Begin the message.
          Connector->Property["SoapAction"] = L"http://www.waytech.com.cn/webservices/WTAU/WTAU0";
          hr = Connector->BeginMessage();
         
          // Create the SoapSerializer object.
          hr = Serializer.CreateInstance(__uuidof(SoapSerializer30));
         
          // Connect the serializer object to the input stream of the connector object.
          hr = Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));
         
          // Build the SOAP Message.
     
          hr = Serializer->StartEnvelope("", "", "");
    //      Serializer->SoapNamespace(L"xsi", L"http://www.w3.org/2001/XMLSchema-instance");
    //      Serializer->SoapNamespace(L"xsd",L"http://www.w3.org/2001/XMLSchema");
         
          hr = Serializer->StartBody(L"");
     
          Serializer->StartElement(L"request", "", "", "");
         
          hr = Serializer->StartElement(L"WTAU1", "", "","");
       //   Serializer->SoapNamespace("", "http://www.waytech.com.cn/webservices/WTAU");
          hr = Serializer->StartElement(L"Module", "", "", "");
         
          hr = Serializer->StartElement(L"ProdType","","","");
          hr = Serializer->WriteString(L"003");
          hr = Serializer->EndElement();
         
          hr = Serializer->StartElement(L"ProdSubType","","","");
          hr = Serializer->WriteString(L"003.0001");
          hr = Serializer->EndElement();
         
          hr = Serializer->StartElement(L"Version","","","");
          hr = Serializer->WriteString(L"1.0.0.0");
          Serializer->EndElement();
         
          hr = Serializer->StartElement(L"TimeStamp","","","");
          hr = Serializer->WriteString(L"2004 12 31 00:00:00");
          hr = Serializer->EndElement();
         
          hr = Serializer->StartElement(L"Name","","","");
          hr = Serializer->WriteString(L"RV.EXE");
          hr = Serializer->EndElement();
         
          hr = Serializer->StartElement(L"FileName","","","");
          hr = Serializer->WriteString(L"RV.EXE");
          hr = Serializer->EndElement();
     
          hr = Serializer->EndElement();
          hr = Serializer->EndElement();
          Serializer->EndElement();
          hr = Serializer->EndBody();
          hr = Serializer->EndEnvelope();
         
         
          // Send the message to the XML Web service.
          hr = Connector->EndMessage();        
         
          // Read the response.
          hr = Reader.CreateInstance(__uuidof(SoapReader30));
         
          // Connect the reader to the output stream of the connector object.
          Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
         
          // Display the result.
          printf("Answer: %s\n", (const char*)Reader->Dom->xml);     
    }
     
    int main()
    {
          CoInitialize(NULL);
          Get();
          CoUninitialize();
          return 0;
    }
    I use a protocol sniffer to capture the request message it generate and found it is like these:
    <?xml **UnReg**1.0" encoding="UTF-8" standalone="no"?>
    <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="" xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema"
     
    xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/"
     
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body SOAP-ENV:encodingStyle="">
    <request SOAP-ENV:encodingStyle="">
    <WTAU1 SOAP-ENV:encodingStyle="">
    <Module SOAP-ENV:encodingStyle="">
    <ProdType SOAP-ENV:encodingStyle="">003</ProdType>
    <ProdSubType SOAP-ENV:e**UnReg**yle="">003.0001</ProdSubType>
    <Version SOAP-ENV:encodingStyle="">1.0.0.0</Version>
    <TimeStamp SOAP-ENV:encodingStyle="">2004 12 31 00:00:00</TimeStamp>
    <Name SOAP-ENV:encodingStyle="">RV.EXE</Name>
    <FileName SOAP-ENV:encodingStyle="">RV.EXE</FileName>
    </Module>
    </WTAU1>
    </request>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
     
    you can see that the first line is wrong, the node "ProdSubType" is wrong too, why will this happen, what should i do to sovle this problem, i hope you can help me.

     
    learn to be still.
    Generaljava and SOAPmemberramzi17 May '01 - 0:33 
    thank u Catalin for the response but the problem that if u know the details that i've implemented the server side and i need to set 4 client in C++,VB,ASP and java the three C++,VB,ASP were set up but i wish i've the solution for the java client i've tried to proceed like the C++ SOAP client given in this site but i failed.
    do u understand me.
    if u want more details this is my e-mail ramoua@yahoo.com.
    thanks.

    GeneralSOAP+javamemberramzi16 May '01 - 5:21 
    hi
    i've succeeded to set c++ SOAP example and i want to know if someone tell me how to set up a java cliant to call webservice implemented with Microsoft SOAP toolkit 2.0
    GeneralRe: SOAP+javamemberCatalin Hatmanu16 May '01 - 6:49 
    An webservice implemented with MS SOAP 2.0 support WSDL, so any toolkits that support WSDL can be a choice for you to implement a client for the wanted webservice; IBM has a java based toolkit for SOAP but I don't know if support WSDL ;
    U can check that at www.alphaworks.com ( or something like that ! )
     

     

     
    Catalin

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Permalink | Advertise | Privacy | Mobile
    Web03 | 2.6.130523.1 | Last Updated 8 Feb 2001
    Article Copyright 2001 by Catalin Hatmanu
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid