This part of the example examines the technique of setting the parse map’s parameters as optional and how to handle data provided to an optional parameter. It also discusses the pitfalls of setting all parameters as required or all parameters as optional. Finally, it describes possible errors from failing to match the parameters with specified defaults.
In the example, the server MOOSE
contains the DLL SURVEY.DLL
, which contains the CHttpServer object CServerDerived
. The client could use the following URL to invoke the RegisterUser
command:
http://moose/survey/survey.dll?RegisterUser?Richard&M%2E&Jones
This command calls the member function RegisterUser
with the parameters “Richard”, “M.”, and “Jones” for the pstrFirst, pstrMiddle, and pstrLast parameters, respectively.
Suppose the client used the following URL to call the RegisterUser
function:
http://moose/survey/survey.dll?RegisterUser?Richard&Jones
Such a call would get an error from the server because in this example all three parameters — pstrFirst, pstrMiddle, and pstrLast — are required. You can make parameters optional by specifying defaults for them in the ON_PARSE_COMMAND_PARAMS macro. This map makes all of the parameters optional:
BEGIN_PARSE_MAP(CServerDerived, CHttpServer)
ON_PARSE_COMMAND(RegisterUser, CServerDerived, ITS_PSTR ITS_PSTR ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("First=~ Middle=~ Last=~")
END_PARSE_MAP(CServerDerived)
The default parameters specified above are tildes, an easily identifiable character you can test for in your handling function.
If the client invokes RegisterUser
by using the following URL:
http://moose/survey/survey.dll?RegisterUser?Richard
when you have the above map installed, the second and third parameters are resolved as tildes.
If the client invokes RegisterUser
by using the following URL:
http://moose/survey/survey.dll?RegisterUser?Richard&M%2E&Jones
when you have the above map installed, all three parameters to the RegisterUser
function will resolve correctly.
You can make some parameters optional and some parameters required, but the required parameters must always appear first ? before any optional parameters. For example, you can modify the map to indicate that only the parameter for the middle name is optional:
BEGIN_PARSE_MAP(CServerDerived, CHttpServer)
ON_PARSE_COMMAND(RegisterUser, CServerDerived, ITS_PSTR ITS_PSTR ITS_PSTR)
ON_PARSE_COMMAND_PARAMS("Last First Middle=~")
END_PARSE_MAP(CServerDerived)
Take care that the parameter types you specify match the parameter defaults you specify. You can accept both a string and an integer, for example,
BEGIN_PARSE_MAP(CServerDerived, CHttpServer)
ON_PARSE_COMMAND(Enlist, CServerDerived, ITS_PSTR ITS_I4)
ON_PARSE_COMMAND_PARAMS("Title=Developer Level=14")
END_PARSE_MAP(CServerDerived)
and produce the expected results. But if you were to reverse the two parameters, like this:
BEGIN_PARSE_MAP(CServerDerived, CHttpServer)
ON_PARSE_COMMAND(Enlist, CServerDerived, ITS_PSTR ITS_I4)
ON_PARSE_COMMAND_PARAMS("Level=14 Title=Developer")
END_PARSE_MAP(CServerDerived)
the default parameter for what you expected to be the level would be 0 and the title would be the string “14”.
To add a space to a default string, enclose the string in single quotation marks. You don’t need to escape special characters.
ON_PARSE_COMMAND_PARAMS("Title='Technical Writer' Level=14")
When passing an unknown number of parameters to the ISAPI extension, use the symbol ITS_RAW. For example, if your web page has a selection list from which one or more items can be selected, the following ON_PARSE_COMMAND specification is not appropriate, because its parameter list specifies that it receive exactly two pointers to strings:
ON_PARSE_COMMAND(Enlist, CServerDerived, ITS_PSTR ITS_PSTR)
If the ISAPI extension were to receive more or fewer than the specified number of parameters, an error will occur on the server. When the number of parameters to be passed is uncertain, you should call ON_PARSE_COMMAND with ITS_RAW. Note that you do not call ON_PARSE_COMMAND_PARAMS when parsing raw data. However, you must call DEFAULT_PARSE_COMMAND to specify the function that will pass the raw data:
BEGIN_PARSE_MAP(CDerivedExtension, CHttpServer)
DEFAULT_PARSE_COMMAND(Myfunc, CDerivedExtension)
ON_PARSE_COMMAND(Myfunc, CDerivedExtension, ITS_RAW)
END_PARSE_MAP(CDerivedExtension)
Use the following function prototype to send the data:
void CDerivedClass::Myfunc(CHttpServerContext* pCtxt, void* pVoid, DWORD dwBytes);
The pVoid pointer points to the data sent to your extension. The dwBytes parameter has a count of bytes at pVoid. If dwBytes is zero, it might indicate that pVoid points to nothing.
If the client invokes RegisterUser
by using the following URL:
http://mooseboy/derived.dll?Myfunc&selection=10&selection=35&confirm=y
Myfunc would be called with pVoid pointing to the string "Myfunc&selection=10&selection=35&confirm=y" and dwBytes containing 42. Note that dwBytes does not count the trailing nul byte in the data referenced by pVoid, because pVoid points to exactly what the client sent to the extension. The client might or might not have sent a trailing nul byte, or it might have sent more than one nul byte in the data.
See Also CHttpServer, CHttpServerContext, CHtmlStream, ON_PARSE_COMMAND, DEFAULT_PARSE_COMMAND, Internet: Where Is...