This documentation is archived and is not being maintained.

Managing Required and Optional Parameters 

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.

Managing a Known Number of Parameters

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:


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:


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_PARAMS("First=~ Middle=~ Last=~")

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:


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:


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_PARAMS("Last First Middle=~")

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_PARAMS("Title=Developer Level=14")

and produce the expected results. But if you were to reverse the two parameters, like this:

BEGIN_PARSE_MAP(CServerDerived, CHttpServer)
ON_PARSE_COMMAND_PARAMS("Level=14 Title=Developer")

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 do not need to escape special characters.

ON_PARSE_COMMAND_PARAMS("Title='Technical Writer' Level=14")

Managing an Unknown Number of Parameters

When passing an unknown number of parameters to the ISAPI extension, use the specification ITS_RAW or ITS_ARGLIST in the ON_PARSE_COMMAND macro.

Use ITS_RAW when you have no knowledge of the parameter data being passed.

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:


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)

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:


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 null 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 null byte, or it might have sent more than one null byte in the data.

Use ITS_ARGLIST when you know that the parameter data being passed can be parsed into CHttpArg objects.

When you use ITS_ARGLIST, the CHttpServer server object constructs a single CHttpArgList object containing zero or more CHttpArg objects. The CHttpArg objects represent, in order, the individual parameters passed in the URL that activated the CHttpServer command.

For example, the following URL:


indicates the user's selections for three arguments: "hockey" for the first argument, nothing for the second argument, and a combination of "beer" and "nuts" for the third argument. The m_pstrArg, m_pstrValue, and m_pstrRaw values in the respective CHttpArg objects are set accordingly (note that the value of the second argument is an empty string). To see how the server parses these arguments into CHttpArgList and CHttpArg objects, see the diagram in CHttpArgList.

The CHttpArgList object is then sent to a parse map function. To specify this, the ON_PARSE_COMMAND macro in the parse map should use ITS_ARGLIST for the parameter type. Here's an example of a parse map that associates a command function Enlist with the CHttpArgList object CHockeyServer.

BEGIN_PARSE_MAP(CHockeyServer, CHttpServer)

See Also