perfectxml.com
 Basic Search  Advanced Search   
Topics Resources Free Library Software XML News About Us
  You are here: home »» Focus »» MSXML »» C++ Samples » Thursday July 18, 2002 :: Using XMLHTTP Saturday, 23 February 2008
 
Microsoft XML Core Services

Summary
MSXML provides a class called XMLHTTP that is a high-level wrapper around WinInet library. This class implements IXMLHTTPRequest interface and allows sending GET and POST requests over HTTP. We can send and receive any data (not just XML) over HTTP using this class.

Today we'll learn how to use XMLHTTP to send a POST request to a remote server from the client. We'll POST a SOAP request package to the Temperature Web service to get the current temperature given the ZipCode.

This application accepts ZipCode as a command line parameter, if provided, else defaults to value of gszDefZipCode global variable; creates a SOAP request package and POSTs that to the Web service using XMLHTTP. The current temprature is retreived from the SOAP response package using DOM.


Steps
Steps that we followed to create this application:
1. Start Visual C++ 6.0 and create a new Win32 Console Application project.
2. Add the following lines in the stdafx.h:
#include <TCHAR.H>
#include <stdio.h>
#include <time.h>

#import "msxml4.dll"
//       ^^^^^^^^^^^
// If this import statement fails, you need to install MSXML 4.0 SP1 from:
//
// http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/766/msdncompositedoc.xml

#include <msxml2.h>
//       ^^^^^^^^^^
// If this include statement fails, you need to install MSXML 4.0 SP1 SDK from:
//
// http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/766/msdncompositedoc.xml
//
// You also need to add the include file and library search path
// to Visual C++'s list of directories (Tools > Options... > Directories).

using namespace MSXML2;

inline void EVAL_HR( HRESULT _hr ) 
   { if FAILED(_hr) throw(_hr); }
3. The above lines import the MSXML 4 type library and defines a tiny utility function to check the HRESULT value.
4. Next, we create a header file (GlobalDefs.h) and define some global variables.
//	Globals
LPCTSTR	gszPOSTURL = _T("http://services.xmethods.net:80/soap/servlet/rpcrouter");

LPCTSTR	gszPkgSOAP = 
	_T("<SOAP-ENV:Envelope "
		" xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' "
		" xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance' "
		" xmlns:xsd='http://www.w3.org/1999/XMLSchema'> "
		" "
		" <SOAP-ENV:Body>" 
			" <ns1:getTemp xmlns:ns1='urn:xmethods-Temperature' "
			"	     SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'> " 
			"    <zipcode xsi:type='xsd:string'></zipcode> " 
			" </ns1:getTemp> " 
			" </SOAP-ENV:Body> "
		" </SOAP-ENV:Envelope>"
		
	);

LPCTSTR	gszDefZipCode = _T("60195");

#define TEMP_SIZE  _MAX_PATH               // size of short buffer
static _TCHAR   szTemp[TEMP_SIZE];         // multipurpose buffer on stack
static DWORD    dwLen;                     // buffer size
5. In the above lines we define the URL (gszPOSTURL) where we'll POST the SOAP request and the SOAP request XML (gszPkgSOAP) text. Note that in the SOAP request XML above, the value of zipcode element is empty. We'll use DOM in the code to load this XML text and set the value of zipcode element using either the command line parameter or the default value.
6. Here is how the main function looks like:
#include "GlobalDefs.h"
#include "Utils.h"

int main(int argc, char* argv[])
{
	try
	{
		EVAL_HR(CoInitialize(NULL));

		//	Make sure that MSXML 4.0 is installed
		if (!isMSXMLInstalled())
			return -1;

		_bstr_t strZipCode;
		
		//	if ZipCode command-line parameter not passed
		if (argc < 2)
			strZipCode = gszDefZipCode;
		else
			strZipCode = argv[1];

		float fTemp = -1;

		//	Utility function that sends a SOAP POST to
		//	a Web service using MSXML XMLHTTP
		getZipCodeTemp(strZipCode, &fTemp);

		if (fTemp > 0)
		{
			printf("\nCurrent temprature at %s zipcode area is %.2f.\n", 
				(LPCSTR)strZipCode, fTemp);
		}
		else
		{
			printf("An error occurred.");
		}
	}
	catch(...)
	{//exception handling
	}
	
	_ftprintf(stdout, "\n\nPress Enter to continue...");
	getchar();
	CoUninitialize();
	return 0;
}
7. The main function starts with a utility function to make sure MSXML is installed. See past sample applications or download the code for this sample for more details on isMSXMLInstalled utility function.

We then set the strZipCode from the command line parameter (if passed) or from the global variable (default value).

Next, we call another utility function getZipCodeTemp which accepts the ZipCode (first parameter), sends the POST request and returns the current temprature as a floating point number (second parameter).

8. Here is how getZipCodeTemp function looks like:
void getZipCodeTemp(const _bstr_t &strZipCode, float* fTemp)
{
	try
	{
		//	Step 1: Load the SOAP message XML using gszPkgSOAP global variable
		IXMLDOMDocument2Ptr pXMLDoc = NULL;
		EVAL_HR(pXMLDoc.CreateInstance("Msxml2.DOMDocument.4.0"));
		
		//	Load the document synchronously
		pXMLDoc->async = false;

		//	Load the XML document
		pXMLDoc->loadXML(gszPkgSOAP);


		//	Step 2: Update the zipcode node in the SOAP XML message

		//	Assuming "zipcode" node will always be there
		//	skipping the step to check if it exists
		pXMLDoc->selectSingleNode("//zipcode")->nodeTypedValue = strZipCode;
		
		//	Step 3: Create XMLHTTP and send a POST request to the Web service
		IXMLHTTPRequestPtr pXH = NULL;

		EVAL_HR (pXH.CreateInstance("Msxml2.XMLHTTP.4.0"));

		EVAL_HR (pXH->open("POST", gszPOSTURL, 
			_variant_t(VARIANT_FALSE), _variant_t(""), _variant_t("")));

		EVAL_HR (pXH->setRequestHeader("Content-Type", "text/xml"));

		EVAL_HR (pXH->send(pXMLDoc->xml));

		//	Step 4: If we got back the success response back
		//	get the value of "return" node from the response SOAP 
		//	message
		if (pXH->status == 200)
		{//	Success

			pXMLDoc = pXH->responseXML;

			//	Assuming "return" node will always be there
			//	skipping the step to check if it exists
			_bstr_t strTemp = pXMLDoc->selectSingleNode("//return")->nodeTypedValue;

			*fTemp = (float)atof(strTemp);
		}
		else
		{
			*fTemp = (float)-1;
		}
		
	}
	catch(...)
	{//	Exception handling

	}
}
9. As mentioned earlier, we first load the SOAP request XML text (gszPkgSOAP) using MSXML DOM and update the value of zipcode node using selectSingleNode method and nodeTypedValue property.

We then create an instance of XMLHTTP object, and call open, setRequestHeader, and send methods on it.

If the POST was successful (status == 200), the response SOAP XML would be available in the XMLHTTP's responseXML property. We use this property to get to the return node in the response SOAP package, convert this string to float and return it to the main function.


Here is the text from the Readme.txt file included with the code download.
Sample Application to illustrate using MSXML 4.0 XMLHTTP class
(IXMLHTTPRequest interface) to send a HTTP request.

The XMLHTTP class uses the WinInet library and supports sending
requests over HTTP. The standard HTTP operations (GET and POST) 
are supported. Supports Synchronous and Asynchronous HTTP access.

In this application, we'll use MSXML DOM and XMLHTTP to POST
a SOAP request to a Web service and process the response. The
Web service we'll be using in this application returns the
current temprature given the Zipcode.

This application accepts ZipCode as a command line parameter,
if provided, else defaults to value of gszDefZipCode global 
variable; creates a SOAP request package and POSTs that to the 
Web service using XMLHTTP. The current temprature is 
retreived from the SOAP response package using DOM.
	
More details on the Temprature Web service can be found at
http://www.xmethods.com/ve2/ViewListing.po?serviceid=8.


--------------------------------------------------------------
Copyright (C) 2002 http://www.perfectxml.com

Created: Thursday, July 18, 2002

Author: perfectxml.com Team (msxml@perfectxml.com)
--------------------------------------------------------------


More Information


  Contact Us | E-mail Us | Site Guide | About PerfectXML | Advertise ©2004 perfectxml.com. All rights reserved. | Privacy