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 );
hr = packer->LoadServicesDescription(ROPE::icURI,
bstrLocation, NULL, &nSuccess);
if( nSuccess != 1 )
throw E_FAIL;
hr = packer->get_GetServiceDescriptors(ROPE::icENDPOINTINFO, &varTemp);
pIUnknown.Attach( varTemp.pdispVal );
pIUnknown.QueryInterface( &pIServiceDescriptors );
VariantInit(&varTemp);
hr = pIServiceDescriptors->get_Item(variant_t(item),&varTemp);
pIUnknown.Detach();
pIUnknown.Attach( varTemp.pdispVal );
hr = pIUnknown.QueryInterface( &pISDEndPointInfo );
hr = pISDEndPointInfo->get_URI(&URI_LISTENER);
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 );
hr = packer->LoadServicesDescription(ROPE::icSTRING,
bstrSrvDesc, NULL, &nSuccess);
if( nSuccess != 1 )
throw E_FAIL;
hr = packer->GetMethodStruct(CComBSTR("GetStockQuote"), ROPE::icINPUT, &bstrRequestStruct);
hr = packer->SetPayloadData(ROPE::icREQUEST, CComBSTR(""),
CComBSTR("GetStockQuote"), bstrRequestStruct);
hr = packer->SetParameter( ROPE::icREQUEST, CComBSTR("Symbol"), CComVariant("MSFT") );
hr = packer->SetParameter( ROPE::icREQUEST,
CComBSTR("description"), CComVariant("any company") );
hr = packer->GetPayload( ROPE::icREQUEST, &bstrRequestPayload);
std::cout << W2A(bstrRequestPayload) << std::endl << std::endl;
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;
hr = packer->SetPayload( ROPE::icRESPONSE, bstrResponsePayload);
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.