Current area: HOME -> Discover ISAPI. Working with GET-POST data
|

Introduction
This article presents a way to retrieve the GET-POST data from a form in an ISAPI extension. Two helpful collections class of parameters
are also provided. Because a non MFC ISAPI extension is more reliable regarding the speed and the simultaneous number of connections, a non MFC version
is included.
Functionality
Both MFC and Non MFC versions use Vector, Map and String STL based classes, with non MFC code inside.
In the MFC version the string collection are based on _bstr_t type. In Non MFC
version the string collection are based on STL String type. So, the MFC version
is using the ISAPI MFC based macros to retrieve the server variables and parameters data while the
non MFC
version uses the WriteClient and ServerSupportFunction HTTP functions.
The default method writes to the browser a complex form with check boxes, edit boxes, radio buttons, text
area - even a
file type edit box. The idea is to receive all the POST parameters into the same DLL extension.
The form is loaded from a HTML string resource using the LoadLongResource helper function.
This reduces the time needed to build the
page because the string is loaded into memory on the first call of the extension. How to use the HTML string resources
in your Visual Studio project it is show in my ADO Data access from ISAPI article.
The GET data is received very easy since that type of data is sent from the browser to
the server using the URL. The POST data
variables are transparent to the user and it is possible to transfer large amount of
data. For more information about GET/POST
data see my HTTP GET-POST utility article.
MFC version
The C++ classes used to store parameters from the data collection are Twin and
TwinVector. The Default method of the ISAPI MFC version writes to the client browser the
IDR_HTML_FORM resource. FormRequest is the method that receives the control after you click on
the "Submit Query" button.
void CPostDataExtension::FormRequest(CHttpServerContext* pCtxt,
void* pVoid, DWORD dwBytes)
{
//build the STL collection from server variables and POST data
TwinVector vecServerCtx(pCtxt, (LPTSTR)pVoid);
//write on browser stream the server context variables
WriteServerData(pCtxt);
//write on browser stream the STL collection of
//server context variables and POST data
WriteServerVar(pCtxt, vecServerCtx);
}
A little problem is to get the control from the DLL entry
point to FormRequest method. Under the MFC, that is done very easy, using the
macros:
DEFAULT_PARSE_COMMAND(FormRequest, CPostDataExtension)
ON_PARSE_COMMAND(FormRequest, CPostDataExtension, ITS_RAW)
To correctly know what method will receive the POST data, the MFC wrapper must receive from
the HTML form one hidden parameter, which must be in the first
place after the FORM HTML tag:
<form action="PostData.dll?" method=post>
<input TYPE=hidden NAME="MfcISAPICommand" VALUE="FormRequest">
In the WriteServerVar helper function, the server context variables collection is written on the HTTP stream.
It's possible to directly obtain the value of a needed parameter:
bstrValue = vecServerCtx.Find(L"Filename").
for (itVec = vecServerCtx.begin(); itVec != vecServerCtx.end(); itVec++)
*pCtxt << GetName() << " = " << GetValue() << "br";
In the same WriteServerVar helper function, the POST data
collection is written to the HTTP stream in this way.
bstrToken = L"DATA";
index = vecServerCtx.Find(bstrToken);
if (index > -1)
{
map = vecServerCtx[index].GetValueAsMap();
if (!map.empty()) //we have values
for (itMap = map.begin(); itMap != map.end(); itMap++)
*pCtxt << (*itMap).first << " = "
<< (*itMap).second << "br";
}
It's possible to directly obtain the value of a needed parameter:
*pCtxt << "Filename = " << map[L"Filename"] << "br".
The TwinVector class offer the VARIANT GetVariant() method and
TwinVector(VARIANT varSafe) constructor, to easy transport the collection over network between COM+ components.
Non MFC version
The non MFC version is based on the MSDN article regarding at GET-POST data
in ISAPI extensions.
The C++ extension receive the entry point in the DWORD WINAPI HttpExtensionProc( LPEXTENSION_CONTROL_BLOCK pECB ) method.
Here it launches the Run method of the CWriteFormExtension class -
there isonly one running object in our ISAPI extension.
The C++ classes used to keep the parameters in the data collection are MultipartParser
and MultipartEntry. The cParser variable of
inherited Map STL type receive the entire collection of POST data. That is done in
Initialize method. The GetParam is a helper method who return the value of a needed parameter.
String CWriteFormExtension::GetParam(MultipartParser& cParser, String sName)
{
String sValue; //the output string
MultipartEntry* pEntry = cParser[sName.c_str()];
if(pEntry != NULL) //we have data
{
sValue = (LPCTSTR) pEntry->Data(); //get value from collection
int nLen = sValue.size();
if(sValue[nLen - 1] == '\n' && sValue[nLen - 2] == '\r')
sValue = sValue.substr(0, nLen - 2);
}
return sValue;
}
This is the result of the Run method:

The LoadLongResource private function is a little
modified compared with the MFC version. The input/output str string
parameter is of STL string type. In the szPath char variable we must put the name of
the DLL file in order to load the correct resource library.BOOL CWriteLayoutExtension::LoadLongResource(String &str, UINT nID)
{
HRSRC hRes;
BOOL bResult = FALSE;
CHAR szPath[MAX_PATH];
strcpy(szPath, "WriteForm.dll");
HINSTANCE hInst = LoadLibrary(szPath);
//if you want standard html type
hRes = FindResource(hInst, MAKEINTRESOURCE(nID), RT_HTML);
if (hRes == NULL)
{
//trace error
str = "Error: Resource could not be found\r\n";
}
else
{
DWORD dwSize = SizeofResource(hInst, hRes);
if (dwSize == 0)
{
str.empty();
bResult = TRUE;
}
else
{
HGLOBAL hGlob = LoadResource(hInst, hRes);
if (hGlob != NULL)
{
LPVOID lpData = LockResource(hGlob);
if (lpData != NULL)
{
str = (LPCTSTR)lpData;
bResult = TRUE;
}
FreeResource(hGlob);
}
}
if (!bResult)
str = "Error: Resource could not be load\r\n";
}
return bResult;
}
About Adrian Bacaianu
I make programming for over 4 years and extensive experience in C++, ASP, Pascal, MFC, COM+, ATL, TCP/IP, HTTP protocols, XML, XSL, SOAP and SQL.
For the last 2 years i working extensively at the background of financial sites (databases, n tier architecture).
I’m available for contracts and/or outsourcing. Contact adrian_bacaianu@yahoo.com.
| User Comments |
 |
 |
|
Think you've can write or have written a good article?
Want to get it hosted for free on a highly respected programming site?
Get the attention you deserve! Click here to find our more
|