MFC ISAPI Extensions Hit Light Speed, Part 2

ISAPI extensions let you create online forms. This month, finish the ISAPI extension you began in Part 1 of this series.

Christa Anderson

November 30, 1996

9 Min Read
ITPro Today logo

MFC Extensions Hit Light Speed

If you need Web speed, you need Internet Server API (ISAPI) Extensions. AnISAPI Extension DLL lets you replace the slow and resource-hogging CommonGateway Interface (CGI) for such purposes as processing fill-in forms. As Part 1of this series (October 1996) explained, CGI scripts and executables run in aseparate process space. ISAPI runs in the same process space as the HTTP server,so ISAPI allows faster startup and communication than other types of CGI. Inaddition to faster connections, ISAPI increases the speed of Microsoft'sInternet Information Server (IIS) because with ISAPI, IIS can use threading toprocess more than one request at a time.

To create an ISAPI Extension, you can start from scratch or simply use theMicrosoft Foundation Class (MFC) ISAPI Wizard. If you choose MFC wizardry,you'll finish very quickly. In addition, you can use the methodology thisarticle presents to create functional ISAPI Extension CGI replacements quicklyand consistently. You'll need IIS or another ISAPI HTTP server installed on aWindows NT server, Microsoft Visual C++ 4.1 or later, and a CGI-compatible Webbrowser, such as Internet Explorer or Netscape.

Part 1 showed how to create an ISAPI Extension that responds to a fill-inform. The code did not do anything except display a default message. Thisarticle shows how to modify an ISAPI Extension that the MFC Wizard generates. Icover the Wizard-generated ISAPI Extension additions you need for the exampleform in Part 1. The additions let you initially display the Comment andSuggestion form shown in Screen 1 as the default and display the second pagewith the return email address and link to the all-records page. The HTML thatproduces the Comment and Suggestion fill-in form is in Listing 1.

ISAPI Wizardry Revisited
After you prepare the HTML for the fill-in form, as in Listing 1, create anISAPI Extension with the Visual C++ ISAPI Extension Wizard. The Wizard createsan ISAPI Extension with the entire MFC ISAPI framework, but little else. We'llextend this framework to display the Comment and Suggestion form shown inScreen 1 and handle the CGI request generated when a user enters a comment (as you see in Screen 2) and clicks Send on the form.

To generate the initial ISAPI Wizard, start Visual C++, select the Filemenu, and click New. Double-click the Project Workspace option.The New Project Workspace dialog appears. From the Type list, selectISAPI Extension Wizard. In the Name text box, type comment as the name of yourproject. Click Create to pull up the ISAPI Extension Wizard - Step 1of 1 dialog you see in Screen 3. Select Generate a Server Extensionobject to specify that you want an MFC-generated class--an ISAPIExtension--to handle ISAPI Extension, or CGI, requests. Click Finish todisplay the New Project Information dialog. Click OK to completethe task.

Modifying the MFC Wizard ISAPI Extension
So let's walk through a simple, standard methodology to finish the ISAPIExtension created in Part 1 of this series. The ISAPI Extension will display theComment and Suggestion form for a URL that points to the ISAPI Extension with noarguments (http://spain.winntmag.com/comment.dll?). You must add a method,postComments, to the class created by the MFC Wizard, CCommentExtension, toprocess the values passed to the ISAPI Extension DLL when someone selects Sendon this form. Listing 2 shows the prototype for theCCommentExtension::postComments method.

The MFC ISAPI framework uses a CGI request-to-method parse map to determinewhich method of the CCommentExtension class to call and how to map theCGI-request named values to the method's parameters. To set up the parse map forthe comment and suggestion form, add the two lines in Listing 3 to the parse mapat the top of the comment.cpp file. The parse map, an MFC addition, maps theparameters of a specific method of the CComment Extension class(e.g., LPTSTRwhoIsIt) to the named values (e.g., INPUT NAME= "WHOISIT") sent fromthe fill-in form. The first parse map entry line, ON_ PARSE_COMMAND macro,specifies the method name (postComments), the class (CCommentExtension), and thedata type of each of the class method's parameters. The second line specifiesthe named values passed from the form to the ISAPI Extension. These valuescorrespond to the class method's parameters specified in the first macro. Forexample, the first parameter for the postComments method is LPTSTRwhoIsIt. Inthe first macro, ITS_PSTR (a string type) is the type for LPTSTR whoIsIt. In thesecond macro, WHOISIT is the named value associated with this parameter. MFCuses this parse map to associate incoming form data (named values) withparameters to pass to class methods.

Before we add the postComments class method, we need to store and read longstrings of HTML code. More specifically, we want to store as a resource theinitial form and portions of the results page that the postComments methodgenerates. Visual C++ 4.1 includes the WWW QUOTE example, which illustrates howto create a new custom resource type for HTML code. To simplify the process ofloading long HTML strings from resources, we'll borrow some code and techniqueshighlighted in the WWW QUOTE example.

First, incorporate two class methods from this example into your ISAPIExtension class: Copy the WritePage Title and LoadLongResource methods from theWWWQUOTE example and change the class names from CWWWQuote toCCommentExtension to match your class name in the method declarations anddefinitions. You'll use this codelater in this example for reading whole HTMLpages from custom HTML resources. You can put this code into a separate file andcall it helper.cpp for future use in other ISAPI Extension projects.

Now, go to the ResourceView tab on the project workspace window to create anew custom resource. Select Comment resources, click the right mousebutton to get a pop-up menu, and select Insert to display the InsertResource dialog. Select Custom to display the New Custom Resourcedialog. Type HTML, and select OK as shown in Screen 4. Your new resource, HTML, is shown in Screen 5.

Get the HTML code into a resource that you will use to display the fullcomment and suggestion form: Copy all the HTML code in Listing 1 into thecomment.htm file. Now select Comment resources again, click the rightmouse button, and select Import to display the Import Resource dialog.Select the file comment.htm, shown in Screen 6, and click OK to bring up the Custom Resource Type dialog shown in Screen 7. Select the HTML resource, andclick OK. Screen 8 shows that you have imported the file, idr_html2,into the project as an HTML custom resource that you can edit.

Now change the resource ID to something more meaningful. Select idr_html2,click the right mouse button, and select Properties to display the CustomResource Properties dialog shown in Screen 9. Select the ID:field, and change the ID to idr_html_comment_form.

To store resources for the two pages that result from clicking Send,you'll need to create two other HTML files and the custom HTML resources forthem. Listing 4 shows two HTML strings. Copy the first HTML string into a filenamed comsent.htm and the second into sugsent.htm. Use the technique describedabove to import these two other HTML files as custom HTML-type resources(idr_html_comsent_form and idr_html_sugsent_form). Next, add the resources (HTMLtitles) shown in Table 1 to the string table resource shown in ResourceView.

Now you're ready to add a few bits of code to make this methodology work.First, change the code in the CCommentExtension::Default method to match Listing5 to display the comment and suggestion form by default. When a user enters the URL http://your machine/comment.dll?, the Comment and Suggestion form is displayed.

This routine writes the form title by calling the WritePageTitle() methodand then uses the custom HTML resource idr_html_comment_form to call theLoadLongResource() method to load the HTML fill-in form. You also see calls tothe StartContent() and EndContent() methods at the beginning and end of thisroutine. The calls write out the initial CGI line that specifies content type(Content-Type:text/htmlr) and the end of the HTML (),respectively. For the CCommentExtension::postComments to process the CGI requestthat the form will produce, you need to add the code in Listing 6.

The postComments method calls the WritePageTitle() method to create thetitle and then calls the LoadLongResource() method to load the HTML. You see thesame technique in the CCommentExtension::Default method (shown in Listing 5 onpage 108) to create the HTML for the title and body. The postComments methodchecks whether this form request was for a comment or a suggestion and sets thetwo resource IDs for the call to the WritePageTitle() method. The HTML andstring-table resource entries for these two resource IDs use the word commentor suggestion to correspond with the button selected.

Once you compile, you've completed the basic tasks for modifying the MFCWizard-generated ISAPI Extension. Your ISAPI Extension will now display andprocess the Comment and Suggestion fill-in form.

Adding Complexity to Your Code
Now if you want to try a more complicated extension, you can add a hyperlinkto a page with all the comments and suggestions. Let's add a new method,AppendToAllReceivedPage(). This method appends the response page to the end ofthe All Received HTML file with all the comments and suggestions yourISAPI Extension DLL has received so far. You'll hyperlink this All ReceivedHTML page to the HTML that is loaded in postComments, as shown in Screen 10. Ifsurfers click the hyperlink, they'll see the entire page of comments andsuggestions, as shown in Screen 11.

You add the call to this method, shown in Listing 7 (on page 108), at theend of the postComments method. Make certain that two CGI requests do not try towrite to the file at once. Two CGI requests can occur simultaneously because IIScan process more than one request asynchronously by creating a separate threadfor each CGI request. Two or more threads attempting to write to the same fileat the same time might result in garbled text in the file at the very least.Listing 8 ensures that only one thread executes the code at atime. If a thread is in the middle of this method and a second thread starts toexecute it, the second thread hits the EnterCriticalSection() function and waitsuntil the first thread passes the LeaveCriticalSection() function before thesecond thread can continue.

To allow multithreaded access to the All Received HTML file, youmust set up two variables, g_fptr and g_Critical Section, during initializationin the object's constructor method (CComment Extension::CCommentExtension). Youuse these variables to access the file (g_ fptr) and protect the code thatwrites to the file (g_CriticalSection). Likewise, when your object is destroyed,you need to clean up by deleting these variables in the object's destructor(CComment Extension::~CCommentExtension). Listing 9 (on page 108) shows theconstructor and destructor for the CComment Extension class.

Wrapping It Up
You've modified an ISAPI Extension to append to the All RecordsHTML file--and in a safe way. The ISAPI Extension also provides a hyperlink tothis page in its reply to the form request. You can compile this ISAPIExtension, copy it into the wwwroot directory, and run a browser with the URLhttp://yourmachine/comment? to see it in action, as in Screens 1, 2, 10, and 11.

You can use the example you just completed as a guide for furtherextensions. ISAPI Extensions are easy to write, extend, and maintain.Try adding another object class method, writing an HTML file with a fill-in formthat references the new class method as the default did (dll?method), andexperiment. It's a snap!

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like