Click here to Skip to main content
Licence CPOL
First Posted 26 Jan 2001
Views 77,491
Bookmarked 16 times

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

By | 7 Feb 2001 | Article
C++ SOAP client for December 2000 release of MS SOAP Toolkit 1.0 using wire transfer technique
  • 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

    Follow on Twitter Follow on Twitter
    binaryfog.com
    zephyr.binaryfog.com

    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. (secure sign-in)
     
    Search this forum  
     FAQ
        Noise  Layout  Per page   
      Refresh
    QuestionSOAP response is ? PinmemberILoveMJ2:55 18 Dec '06  
    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? Pinmembergxulg19:08 16 Jan '05  
    Generaljava and SOAP Pinmemberramzi0:33 17 May '01  
    GeneralSOAP+java Pinmemberramzi5:21 16 May '01  
    GeneralRe: SOAP+java PinmemberCatalin Hatmanu6:49 16 May '01  

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

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

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