C++ SOAP Client for MS SOAP Toolkit 1.0 using Wire Transfer Technique






4.67/5 (3 votes)
C++ SOAP client for December 2000 release of MS SOAP Toolkit 1.0 using wire transfer technique
Requirements
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 released. 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 the Sample
MS provided, for testing purposes, the web service. The web service description can be found at the following link. The sample uses 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 string
s (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 successful "<< 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 sent 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;
}
Conclusion
I hope you will find this approach useful.