65.9K
CodeProject 正在变化。 阅读更多。
Home

使用线传输技术为 MS SOAP Toolkit 1.0 开发的 C++ SOAP 客户端

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (3投票s)

2001 年 1 月 27 日

CPOL
viewsIcon

97012

downloadIcon

1505

使用线传输技术为 2000 年 12 月发布的 MS SOAP Toolkit 1.0 开发的 C++ SOAP 客户端

要求

引言

2000 年 7 月,微软发布了 Visual Studio 6.0 的第一个 SOAP Toolkit 版本。2000 年 9 月,发布了 SOAP Toolkit 版本 1.0 的 Beta 1 版本。我认为最显著的特性是增加了 SSL 支持。最新的非 Beta 版本是 2000 年 12 月的版本,修复了错误并对暴露的接口进行了小幅更改。本文的目的是演示使用 C++ 客户端和 ATL 使用线传输技术。

关于示例

MS 为了测试目的,提供了 Web 服务。Web 服务的描述可以在以下 链接 中找到。该示例使用此 Web 服务,并演示了执行此 Web 服务暴露的 GetStockQuote 方法。该示例包含两种方法,ConnectGetStockMethod

Connect 方法

此方法用于从 Web 服务获取服务描述和 URI 侦听器。这是两个 string(BSTR)我们将保留用于在 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

此方法用于调用 Web 服务暴露的 GetStockPrice 方法。在创建新的 SOAPPackager 对象并从 Connect 方法获得的 string 加载服务描述后,将创建有效负载并发布(使用新的 WireTransfer 对象)到 Web 服务,并将显示结果

	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;
	}

结论

我希望您会发现这种方法有用。

© . All rights reserved.