// soapconsole.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
//步驟
//1.導入類型庫
//2.需要創建一個SoapConnector
//3.下一步創建SoapSerializer
//4.下一步把消息附加到SoapConnector的輸入流
//5.下一步讀取結果.要讀取服務器的回復,客戶端應用需要使用SoapReader,
// 6.SoapReader被連接到SoapConnector輸出流
// 7.用IXMLDOMElement對象可以從SoapReader里讀到服務器的回復
///////////////////////////////////////////////////////////////////////////////
void Add()
{
try
{
//SoapSerializer用於序列化(串行化),創建,封裝SOAP消息.用來構建一個向Web服務發送的SOAP消息
ISoapSerializerPtr Serializer;
//SoapReader將SOAP消息解析為一個DOM模型,並提供一系列操作該DOM模型的方法
ISoapReaderPtr Reader;
//SoapConnector在對象之間發送和接收SOAP消息的傳輸協議
ISoapConnectorPtr Connector;
//創建一個Connector對象
Connector.CreateInstance(__uuidof(HttpConnector30));
//Web服務是由Property(HttpConnector的一個屬性)指定的
//在處理這一屬性時有件事情需要指定:我們引用的哪個屬性以及該屬性的值
//EndPointURL屬性指定Web服務
Connector->Property["EndPointURL"] = "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl";//web服務的URL
////////////////////////////////////////////////////////////////////////////
//Connector->Property[參數]說明,對大小寫敏感
// AuthPassword: 端點認證用的口令。
// AuthUser: 端點認證用的用戶名
// EndPointURL : 端點的URL
// ProxyPassword: 代理認證的口令
// ProxyPort : 代理服務器使用的端口
// ProxyServer : 代理服務器的IP地址或主機名
// ProxyUser : 代理認證的用戶名
// SoapAction: HTTP頭部中SoapAction中的值。這個屬性只使用於低級API。它將忽略SoapClient接口(高級API)中的ConnectorProperty屬性 。
// SSLClientCertificateName:指定使用Secure Sockets Layer (SSL)加密協議(如果存在,則該字符串標明用於SSL協議中的客戶端證書)。語法如下:
// [CURRENT_USER | LOCAL_MACHINE\[store-name\]]cert-name with the defaults being CURRENT_USER\MY (與Microsoft Internet Explorer用法相同)。
// Timeout: HttpConnector的超時限制,以毫秒為單位。
// UseProxy: 一個類型為布爾型的屬性,表明是否使用代理服務器。缺省情況下,這一屬性的值被設定為False,表明無需使用代理服務器。如果要使用代服務器,需要將該屬性的值設置為True。如果將該屬性的值設置為True, 而又沒有設置ProxyServer屬性,HttpConnector將使用IE中設置的代理服器。HttpConnector會忽略IE中的“不使用代理服務器”設置。
// UseSSL: 表明是否使用了SSL的布爾型值。如果該屬性被設置為True,則無論WSDL中是否指定了HTTP或HTTPS,HttpConnector對象都使用SSL連接。
// 如果該屬性的值被設置為False,則只有在WSDL中指定了HTTPS的情況下, HttpConnector對象才會使用SSL連接
// 詳細請參考:http://www.codesky.net/article/200504/62841.html
///////////////////////////////////////////////////////////////////////////
Connector->Connect();
//開始消息
Connector->Property["SoapAction"] = "http://WebXml.com.cn/getWeatherbyCityName";
//開始SOAP消息
//在完成與Web服務的連接和其他的細節后,我們就可以調用向服務器發送SOAP信息的方法了,必須在調用SoapSerializer的其他方法之前調用該方法
Connector->BeginMessage();
//創建SoapSerializer對象
Serializer.CreateInstance(__uuidof(SoapSerializer30));
//將serializer連接到connector的輸入字符串
//在與服務器連接前,SoapSerializer對象必須與SoapConnector對象連接。
//為了使這二個對象相互連接,我們需要調用SoapSerializer對象的Init方法,該方法需要一個參數InputStream(向服務器發送數據的流)
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));
//創建SOAP消息
//開始處理SOAP消息,
//第一個參數是命名空間,缺省為SOAP-ENV,第二個參數定義URL,第三個參數定義Serialzier->startBody("")函數的編碼方式。
Serializer->StartEnvelope("","","");
//開始處理Body元素,參數為URI的編碼類型,缺省為NONE
Serializer->StartBody("");
//開始處理Body里的子元素
//第一個參數是元素名,第二個參數是URL,第三個參數是編碼類型,第四個參數是元素的命名空間
Serializer->StartElement("getWeatherbyCityName", "http://WebXml.com.cn/","","soap");
//WebXml.com.cn是Web服務所屬的名稱空間(如果Web服務提供者沒有指定名稱空間,將會使用該默認名稱空間)。
Serializer->StartElement("theCityName","","","soap");
//寫入元素值,
Serializer->WriteString("鄭州");
//上面的每個startXXX函數后都要有相應的endXXX函數來結尾
Serializer->EndElement();
Serializer->EndElement();
Serializer->EndBody();
Serializer->EndEnvelope();
//消息做完之后,連接器就調用endMessage()方法將消息發送到服務器
Connector->EndMessage();
//創建響應soap消息
Reader.CreateInstance(__uuidof(SoapReader30));
//OutPutStream來讀取SoapReader對象中的信息
//將reader連接到connector的輸出字符串
Reader->Load(_variant_t((IUnknown*)Connector->OutputStream),"");
//將回應信息加載到SoapReader對象后,就可以用它的RpcResult屬性來獲取結果,
//但是RpcResult並不直接返回結果,它返回Body的第一個實體元素
//然后用text屬性讀取該元素的屬性值
printf("%s\n",(const char*)Reader->RpcResult->text);
}
catch(_com_error &e)
{
printf("%s",e.ErrorMessage());
}
}
int main(int argc, char* argv[])
{
CoInitialize(NULL);
Add();
CoUninitialize();
return 0;
}