Downloads
cmtDLL.zip

Part 1: Creating ActiveX forms on the Web

You've encountered them many times on the Web--those ubiquitous online forms. Home pages feature a variety of such forms for comments and suggestions, order processing, username validation, questionnaires, and searches, to mention a few. Online forms can fulfill each of these requests. Although such forms can also take time to process and add to the load on your Web server, with the right tools, you can create forms that don't drain your system.

With Windows NT Server and Microsoft's Visual C++ (VC++) 4.1, you can use Internet Server Application Program Interface (ISAPI) Extensions that will make your online forms move at light speed. Unlike forms you create with Perl or shell programming, forms based on ISAPI Extensions can improve NT Server's performance and are easy to create using the ISAPI Extension Wizard in the VC++ Microsoft Foundation Classes (MFCs). The Wizard walks you through creating an ISAPI Extension, a framework based on new MFC ISAPI Extension classes. The Wizard gives you easy programming, debugging, and maintenance all in one application.

To create ISAPI Extensions, you need Hypertext Transfer Protocol (HTTP) server software, VC++ 4.1, and a Common Gateway Interface (CGI)-compatible Web browser such as Internet Explorer (IE) or Netscape. The latest Microsoft Developer Network (MSDN) CD-ROM is also helpful for reference, but not required.

This how-to article explains the process of creating a custom ISAPI Extension with the MFC Wizard. You first need to understand CGI, how to create a form with Hypertext Markup Language (HTML) to call the ISAPI Extension, and how to create an ISAPI Extension for your form. Then, you can walk through using the Wizard to create the base implementation for an ISAPI Extension. A follow-on article will cover additions to the Wizard-generated ISAPI Extension that you need to produce and process an online form.

Beyond the Gateway
As Web traffic increases, so does the demand for fast and efficient processing. ISAPI Extensions can speed up your online forms to meet this demand.

All online forms require CGI. When you select Submit on a form, you trigger a CGI request to an HTTP server. The server uses a CGI program to process the CGI request and sends the output back to your Web browser. In turn, your browser interprets the HTML and displays the results as a Web page.

On an NT server, ISAPI Extensions allow speed and efficiency that blow away other CGI programs' performance. At the heart of the efficiency is how Microsoft's Internet Information Server (IIS) uses NT's threading technology and DLL capabilities. Threading increases the server's efficiency: Creating a new thread requires far less system resource than creating a new process, which is what traditional CGI does.

ISAPI Extensions are DLLs loaded into the site's IIS process on demand or at server startup. IIS uses threading to speed up CGI requests to an ISAPI Extension. The server creates a new thread for each CGI request, so the server can handle more than one CGI request at a time.

To handle specific CGI requests, you write a two-line CGI-request to method-name a parse map. The parse map specifies a class-method name you must add to the class the Wizard creates for you. Then, in the online form, you reference the ISAPI Extension filename and class-method name as the form's action. To illustrate this process, let's look at an example.

Creating a CGI Form
The first step in using an ISAPI Extension to generate and process an online form is to prepare the form's HTML. Let's consider an online form that solicits a comment or suggestion, such as the form in Screen 1.

On the form, you can fill in your name, email address, and comment or suggestion. After you click either Comment as in Screen 2, or Suggestion, you select Send to submit your comment or suggestion to the home page's owner or Web master.

When you click Send, you trigger the CGI program associated with the form. Then, as Screen 3 shows, the CGI responds by generating another Web page to confirm receipt of the comment or suggestion. A link on this page connects to another Web page which you see in Screen 4. It lists all comments and suggestions, including any you just submitted.

Listing 1 shows the HTML code for the sample comment and suggestion form. The title and header are the first two lines of code. The title, Comments and Suggestions, appears in the browser title bar, and the header, Comment and Suggestion Fill-out Form, appears at the beginning of the page in the browser. (The code for this example is on the Windows NT Magazine Web site at www.winntmag.com.)

The form body is standard HTML. The two input fields are WHOISIT, which appears next to Your Name:, and EMAIL, which appears next to Your email address:. The form's default value for Your Name: is Anonymous, and the default for Your email address: is myname@company.com.

The form has two mutually exclusive radio buttons, Comment or Suggestion. The CGI request sends a value of 1 for Comment and a value of 0 for Suggestion. The form initially appears with Comment selected. Then, a multiline, text type field, WISEWORDS, appears below the text, Words of Wisdom:. The field has five rows and 80 columns. Finally, you see two unnamed (because they are not on the command line) buttons: a submit button with a value of Send and a reset button with a value of Clear.

The form's first line has the directives ACTION="comment.dll?postComments"

METHOD="POST". The ACTION keyword specifies the CGI script (ISAPI Extension) to execute. You specify the ISAPI Extension as comment.dll, place a separator ?, and specify the name of the class-method (postComments) that will process the form. (This syntax is specific to MFC implementation of ISAPI Extensions.)

In addition to the first directive, the MFC Wizard-generated ISAPI Extension requires the METHOD="POST" directive. The POST method lets the ?postComments portion pass to the ISAPI Extension intact so that MFC knows which class-method to call.

MFC ISAPI Wizardry
After you prepare the HTML for the form, you need to create the ISAPI Extension with the Visual C++ ISAPI Extension Wizard. Start Visual C++, select the File menu, and click New. Double-click the Project Workspace option. The New Project Workspace dialog displays. From the Type list, select ISAPI Extension Wizard. Type comment as the name of your project in the Name text box, as you see in Screen 5. Click Create. The ISAPI Extension Wizard - Step 1 of 1 dialog appears, as in Screen 6.

Select Generate a Server Extension object to specify that you want an MFC-generated class--an ISAPI Extension--to handle ISAPI Extension-CGI requests. You can also select Generate a Filter object, for filtering all HTTP requests, including CGI requests, coming into the IIS HTTP Server. Among the many uses for these requests are providing better or custom logging, security, and maintenance. Click Finish. The New Project Information dialog displays, as Screen 7 shows. Click OK to complete the task.

Now compile the DLL, and copy it to the \wwwroot directory in which your IIS is installed. Then, start IE, Netscape, or any other CGI-compatible browser. Type in the Web address yourmachinename/comment.dll? to run the CGI ISAPI Extension (the question mark tells the HTTP server that you're using a CGI program).

The Wizard will generate the message, "This default message was produced by the Internet Server DLL Wizard. Edit your CCommentExtension::Default() implementation to change it." To begin modifying the code, edit the comment.cpp file. Find the CComentExtension::Default method, and change it to match Listing 2. This change causes the DLL to display "Hello World" instead of "This default message was produced...".

To add commands that the ISAPI Extension can handle, you must include new methods and add a few lines to the parse map at the beginning of the comment.cpp file. (For more information about parse maps, see the MSDN CD, an optional, but highly recommended tool. Search on ISAPI Extensions and Parse Maps, or go to Visual C++ Books\MFC 4.1\Programming with MFC: Encyclopedia\Internet Server API (ISAPI) Extensions\ISAPI Extensions: Parse Maps.)

Before you can debug your ISAPI Extension, you have to stop the WWW, FTP, and Gopher services. You can stop these services through the Internet Service Manager (\inetsrv\admin\inetmgr.exe) or through the Services Control Panel.

The next step is to debug your ISAPI Extension. To test the ISAPI Extension, click Build, and open the Setting dialog. Select the Debug tab. Then in the Executable for debug session text box, type the path to INETINFO.EXE. In the Program arguments text box, type -e W3Svc. Also, go to the Link tab, and set the Output file name to point to the \wwwroot directory for IIS (for example, \activex\inetsrv\wwwroot\comment.dll).

For more information about debugging an ISAPI Extension, see TN063: Debugging Internet Extension DLLs on the MSDN CD. You can also connect to URL: rampages.onramp.net/~steveg/eyesapi.html for the useful EyeSAPI test tool, which emulates ISAPI Extension--CGI requests from an IIS HTTP server.

The Next Step
Now that you've created an example form and used the Visual C++ Extension Wizard to create a basic ISAPI Extension, you can create the additions the Wizard-generated ISAPI Extension needs to produce and process the example form. The next article describes what additions you need and how to create them.

LISTING 1: Example Form HTML
<title>Comments and Suggestions</title>
<h1><b>Comment and Suggestion Fill-out Form</h1></b><p><hr>
<FORM ACTION="comment.dll?postComments" METHOD="POST">
Your Name:<INPUT NAME="WHOISIT" VALUE= "Anonymous" SIZE=16 MAXLENGTH=64>
Your email address:<INPUT NAME="EMAIL" VALUE="myname@company.com" SIZE=21 MAXLENGTH=64><p>
<INPUT TYPE="radio" NAME="COMMENT" VALUE="1" CHECKED> Comment
<INPUT TYPE="radio" NAME="COMMENT" VALUE="0"> Suggestion<p>
Words of Wisdom:<br>
<TEXTAREA NAME="WISEWORDS" ROWS=5 COLS= 80></TEXTAREA><p>
<INPUT TYPE="submit" VALUE="Send">
<INPUT TYPE="reset" VALUE="Clear">
</FORM>

LISTING 2: Modifying the comment.cpp file
void CCommentExtension::Default(CHttpServerContext* pCtxt)
\{
StartContent(pCtxt);
WriteTitle(pCtxt);
CString strOutput;
strOutput = "Hello World!";
*pCtxt << strOutput;
EndContent(pCtxt);
\}