If you are writing a server-side application (such as an ISAPI DLL or a COM DLL to be loaded on the server side), and need to invoke a XML Web Service, you can use MSXML ServerXMLHTTP component.
The following sample C++ application illustrates using MSXML ServerXMLHTTP to invoke a .NET Web Service, either by sending HTTP GET request, or HTTP POST request, or posting SOAP and processing the SOAP response.
This sample application invokes the Weather Info XML Web Service to get the detailed weather information for any given valid US zip code.
The header file (ServerXMLHTTP1.h):
#ifndef _SERVERXMLHTTP1_H_
#define _SERVERXMLHTTP1_H_
#include <atlbase.h>
#import <msxml4.dll> named_guids
using namespace MSXML2;
#define CHECK_HR(hr) { if (FAILED(hr)) { throw -1; } }
// --------------------------------------------------------
static const TCHAR* const g_lpszGetURL =
_T("http://www.ejse.com/WeatherService/Service.asmx/GetWeatherInfo?zipCode=%s");
// --------------------------------------------------------
static const TCHAR* const g_lpszPostURL =
_T("http://www.ejse.com/WeatherService/Service.asmx/GetWeatherInfo");
// --------------------------------------------------------
static const TCHAR* const g_lpszSOAPEndpointURL =
_T("http://www.ejse.com/WeatherService/Service.asmx");
static const TCHAR* const g_lpszSOAPAction =
_T("http://ejse.com/WeatherService/GetWeatherInfo");
static const TCHAR* const g_lpszSOAPReq =
_T("<?xml version='1.0' encoding='utf-8'?> "
"<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
" xmlns:xsd='http://www.w3.org/2001/XMLSchema' "
" xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"
" <soap:Body>"
" <GetWeatherInfo xmlns='http://ejse.com/WeatherService/'>"
" <zipCode>%s</zipCode>"
" </GetWeatherInfo>"
" </soap:Body>"
"</soap:Envelope>");
// --------------------------------------------------------
static const TCHAR* const g_lpszXPathSelNS =
_T("xmlns:ns1='http://ejse.com/WeatherService/'");
// --------------------------------------------------------
//TODO: Move to resource file
static const TCHAR* const g_lpszOutputMsg =
_T("Weather Information - Last Updated %s\n\n"
"\tLocation: %s (%s)\n\tTemprature: %s\n\tForecast: %s\n\t"
"Visibility: %s\n\tHumidity: %s\n\tPressure: %s\n");
// --------------------------------------------------------
#endif // _SERVERXMLHTTP1_H_
The source code file (ServerXMLHTTP1.cpp)
#include "stdafx.h"
#include "ServerXMLHTTP1.h"
// Utility function
void GetXPathExprValue(CComQIPtr<IXMLDOMDocument2> &spResponseXMLDoc,
LPCTSTR lpszXPathExpr,
LPSTR lpszResultValue)
{
USES_CONVERSION;
CComPtr <IXMLDOMNode> spResultNode;
spResultNode = spResponseXMLDoc->selectSingleNode(_bstr_t(lpszXPathExpr));
if(spResultNode.p != NULL)
_tcscpy(lpszResultValue, W2A(_bstr_t(spResultNode->nodeTypedValue)));
}
//------------------------------------------------------------------------------
// Function uses ServerXMLHTTP to send a GET/POST/SOAP request to a .NET Web Services,
// and then uses MSXML DOM to process the response XML text.
//
// Illustrates calling a .NET Web Service either by sending a GET request,
// or a HTTP POST or by using the SOAP method.
//
// iMethod parameter:
// 0 : (Default) HTTP GET
// 1 : HTTP POST
// 2 : SOAP
//------------------------------------------------------------------------------
void CallWebService(LPCTSTR szZipCode, int iMethod = 0)
{
float fTemprature = -999;
USES_CONVERSION;
// Create an instance of ServerXMLHTTP Class
CComPtr<IServerXMLHTTPRequest> spServerXMLHTTP1;
HRESULT hr = spServerXMLHTTP1.CoCreateInstance(CLSID_ServerXMLHTTP40);
CHECK_HR(hr);
TCHAR szGetURL[MAX_PATH*2]={0};
TCHAR szPostValue[MAX_PATH*2]={0};
TCHAR szSOAPReq[MAX_PATH*2]={0};
int iPostDataLen =0;
TCHAR szDataLen[10]={0};
switch(iMethod)
{
case 0: // HTTP GET
sprintf(szGetURL, g_lpszGetURL, szZipCode);
// Initialize the Synchronous HTTP GET request
hr = spServerXMLHTTP1->open(_bstr_t(_T("GET")), szGetURL, VARIANT_FALSE);
CHECK_HR(hr);
// Send the HTTP GET request
hr = spServerXMLHTTP1->send();
CHECK_HR(hr);
break;
case 1: // HTTP POST
_tcscpy(szPostValue, _T("zipCode="));
_tcscat(szPostValue, szZipCode);
iPostDataLen = _tcslen(szPostValue);
itoa(iPostDataLen, szDataLen, 10);
// Initialize the Synchronous HTTP GET request
hr = spServerXMLHTTP1->open(_bstr_t(_T("POST")), g_lpszPostURL, VARIANT_FALSE);
CHECK_HR(hr);
spServerXMLHTTP1->setRequestHeader(_T("Content-Type"),
_T("application/x-www-form-urlencoded"));
spServerXMLHTTP1->setRequestHeader(_T("Content-Length"), szDataLen);
// Send the HTTP POST request, along with the SOAP request envelope text
hr = spServerXMLHTTP1->send(szPostValue);
CHECK_HR(hr);
break;
case 2: // SOAP
sprintf(szSOAPReq, g_lpszSOAPReq, szZipCode);
hr = spServerXMLHTTP1->open(_bstr_t(_T("POST")), g_lpszSOAPEndpointURL, VARIANT_FALSE);
CHECK_HR(hr);
// Set the required SOAPAction and Content-Type headers
hr = spServerXMLHTTP1->setRequestHeader(_T("SOAPAction"), g_lpszSOAPAction);
CHECK_HR(hr);
hr = spServerXMLHTTP1->setRequestHeader(_bstr_t(_T("Content-Type")),
_bstr_t(_T("text/xml")));
CHECK_HR(hr);
// Send the POST request, along with the SOAP request envelope text
hr = spServerXMLHTTP1->send(_bstr_t(szSOAPReq));
CHECK_HR(hr);
break;
}
if(200 == spServerXMLHTTP1->status) //Success
{
// using MSXML DOM to process the response XML text
CComQIPtr <IXMLDOMDocument2> spResponseXMLDoc;
spResponseXMLDoc = spServerXMLHTTP1->responseXML;
spResponseXMLDoc->setProperty(_bstr_t(_T("SelectionNamespaces")), g_lpszXPathSelNS);
TCHAR szLastUpdated[MAX_PATH] = {0};
TCHAR szLocation[MAX_PATH] = {0};
TCHAR szReportedAt[MAX_PATH] = {0};
TCHAR szTemprature[MAX_PATH] = {0};
TCHAR szForecast[MAX_PATH] = {0};
TCHAR szVisibility[MAX_PATH] = {0};
TCHAR szHumidity[MAX_PATH] = {0};
TCHAR szPressure[MAX_PATH] = {0};
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:LastUpdated"), szLastUpdated);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:Location"), szLocation);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:ReportedAt"), szReportedAt);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:Temprature"), szTemprature);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:Forecast"), szForecast);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:Visibility"), szVisibility);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:Humidity"), szHumidity);
GetXPathExprValue(spResponseXMLDoc, _T("//ns1:Pressure"), szPressure);
printf(g_lpszOutputMsg, szLastUpdated, szReportedAt, szLocation,
szTemprature, szForecast, szVisibility, szHumidity, szPressure);
}
else
{
printf(_T("\nError: %s\n"), W2A(spServerXMLHTTP1->statusText));
}
}
// main, The entry point function
int main(int argc, char* argv[])
{
if(argc < 2)
{//insufficient parameters
printf(_T("\nServerXMLHTTP1.exe: Sample Web Service client to get "
" the weather information for a valid given U.S. zipcode\n"));
printf(_T("\nUsage:\tServerXMLHTTP1.exe <US_Zipcode> [<Method (0=GET, 1=POST, 2=SOAP)>]\n"
"Examples:\n\tServerXMLHTTP1.exe 98007\n\t"
"ServerXMLHTTP1.exe 98007 1"));
printf(_T("\n\nPress Enter to continue..."));
getchar();
return -1;
}
try
{
HRESULT hr = CoInitialize(NULL);
CHECK_HR(hr);
// The Method (GET[0]/POST[1]/SOAP[2])
int iCallMethod = 0;
if(argc >= 3 && argv[2] != NULL)
iCallMethod = atoi(argv[2]);
CallWebService((LPCTSTR)argv[1], iCallMethod);
}
catch(int)
{
//TODO: Error handling
printf(_T("Exception raised!"));
}
CoUninitialize();
printf(_T("\n\nPress Enter to continue..."));
getchar();
return 0;
}
Output: