Click here to download a sample console application that uses MFC WinInet classes to call a Web service.
MFC provides wrapper classes around WinInet API. These classes simplify the task of writing HTTP/FTP client applications. Following are the eight steps required to send a HTTP request using MFC WinInet classes:
- Create an instance of CInternetSession class. This begins an HTTP session.
- Call CInternetSession::GetHttpConnection to get an instance of CHttpConnection. Pass the server and HTTP port to this method, and it establishes a connection to an HTTP server.
- Open an HTTP request using CHttpConnection::OpenRequest. Pass the rest of the URL (except server name), the HTTP method (GET/POST/...) to this method, and it returns a CHttpFile object.
- Optionally, call CHttpFile::AddRequestHeaders to supply any request headers.
- Call CHttpFile::SendRequest to actually send the request and get the response back.
- Use CHttpFile::QueryInfoStatusCode to find out if the HTTP request succeeded.
- On success, use pHttpFile->Read to read the response bytes.
- Finally, call CHttpFile::Close and CHttpConnection::Close.
Here is a Web service client code that uses MFC WinInet classes to call Weather - Temperature Web service (written using Apache SOAP) on XMethods.com. This Web service, given a zip code (US only), returns the current temperature.
...
...
#include <afxinet.h>
...
...
static const TCHAR* g_lpszSOAPRequest =
_T("<soap:Envelope "
"xmlns:n='urn:xmethods-Temperature' "
"xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' "
"xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/' "
"xmlns:xs='http://www.w3.org/2001/XMLSchema' "
"xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> "
"<soap:Body soap:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'> "
" <n:getTemp> "
" <zipcode xsi:type='xs:string'>98007</zipcode> "
" </n:getTemp> "
"</soap:Body> "
"</soap:Envelope>");
#define CHUNK_SIZE 2048
void CallWebService()
{
try
{
// 1. Instantiate CInternetSession
CInternetSession httpSession(_T("Sample Web Service Client"),
1,
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
INTERNET_FLAG_DONT_CACHE);
// 2. Get CHttpConnection (Server URL and Port required)
CHttpConnection* pHttpConnection =
httpSession.GetHttpConnection(_T("services.xmethods.net"),
INTERNET_FLAG_NO_AUTO_REDIRECT,
80, NULL, NULL);
// 3. Open HTTP Request (pass method type [get/post/..] and URL path (except server name))
CHttpFile* pHttpFile =
pHttpConnection->OpenRequest
(_T("POST"),
_T("soap/servlet/rpcrouter"),
NULL, 1, NULL, NULL,
INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_EXISTING_CONNECT |
INTERNET_FLAG_DONT_CACHE |
INTERNET_FLAG_RELOAD);
// 4. Add HTTP Request Headers
CString strSOAPReq(g_lpszSOAPRequest);
DWORD dwRewLen = strSOAPReq.GetLength();
CString strHeaders;
strHeaders.Format(_T("Content-Type: text/xml; charset=utf-8/nContent-Length:%d"),
dwRewLen);
pHttpFile->AddRequestHeaders(strHeaders);
// 5. Send the request
pHttpFile->SendRequest(NULL, 0, (LPVOID)(LPCTSTR)strSOAPReq, dwRewLen);
// 6. Check the return HTTP Status Code
DWORD dwStatucCode = HTTP_STATUS_OK;
pHttpFile->QueryInfoStatusCode(dwStatucCode);
if(dwStatucCode == HTTP_STATUS_OK)
{
CString strResponse;
TCHAR szBuf[CHUNK_SIZE] = {0};
UINT nBytesRead;
// 7. Read the response text
do
{
nBytesRead = pHttpFile->Read((void*) szBuf, CHUNK_SIZE);
strResponse += szBuf;
if(nBytesRead < CHUNK_SIZE)
break;
}while(nBytesRead == CHUNK_SIZE);
AfxMessageBox(strResponse);
//TODO: Process the response
}
else
{
//TODO: Error handling
}
// 8. Close the stream/connection
if(pHttpFile)
{
pHttpFile->Close();
delete pHttpFile;
pHttpFile = NULL;
}
if(pHttpConnection)
{
pHttpConnection->Close();
delete pHttpConnection;
pHttpConnection = NULL;
}
}
catch(CInternetException* exp)
{
TCHAR lpszErrorMsg[MAX_PATH+2];
exp->GetErrorMessage(lpszErrorMsg, MAX_PATH);
AfxMessageBox(lpszErrorMsg);
}
}
...
...
Click here to download the above sample console application.