Like so many of the chapters in this part of the book, this one is about putting several of the things you've learned together to create something altogether new on your Intranet. In fact, most of this book is about the use of imaginative elbow grease to create wonderful things on your Intranet; there's more imagination than rocket science involved. The tools you've been learning in this book can be put together to bring off near miracles for your Intranet.
In this chapter, we'll talk about using some of the tools to create
an ordering and inventory application for your Intranet. Keep
in mind while reading this chapter that these techniques are generally
useful on an Intranet, so you need not focus too closely on the
ordering and inventory application used as an example.
Note |
Although this chapter is nominally about creating a specific order and inventory application for your Intranet, the ideas and techniques, including some important CGI scripting tips, aren't limited to this application. You'll be able to use them in other Intranet applications you build, even if you don't build this particular one. |
Before going into a lot of implementation details, let's get a bird's eye view of the application. We'll look first at its basic purpose, then at the customer's view of it, and finally at the component parts of the application.
Your Intranet ordering and inventory application's purpose is to provide your customers with Web-browser access to the underlying company ordering and inventory database. Specifically, your application will:
I won't address specific information about the design of the database application underlying your Intranet application, nor any product-specific recommendations. It's assumed, however, that your in-place database is a relational database application capable of accepting input from HTML forms using CGI or ISAPI. Recall that Visual C++ 4.x includes both an ISAPI Wizard and an ODBC interface (actually two).
In addition, it's assumed the database tracks your inventory, accepts and verifies orders using user account numbers, debits user accounts for orders, and updates inventory once orders are delivered using predefined procedures.
This sort of database application is fairly standard in the corporate world, so details on setting one up aren't provided. If you don't already have such a database in place, refer to Chapter 16, "Linking Databases to the Web," for specifics on how a number of free and commercial databases work in a World Wide Web environment. It's not required that there be a specific Web interface to your particular database; you can always use the CGI mechanism to access it. But it's nice if there is.
The sort of database you'll need to implement the application described in this chapter depends on your organization's needs, anticipated level of use, and other factors. Small operations may be able to use a pc-based database, such as Microsoft Access, accessed using Visual Basic CGI programs from a Web server running on the same pc. (See Chapter 20 for an example.)
The primary viewof your Intranet ordering and inventory application your customers will have is the one they see through their Web browser, of course. Figure 24.1 shows a simple HTML fill-in form for placing orders. As you can see, the form has spaces for customer name, account information, delivery information, and product and vendor information. There are also a couple of free-form text boxes for entering unformatted information. Later in this chapter, you'll see modified versions of this form with additional features that make it easier for your customers to order things. The form interfaces with a CGI or ISAPI program that processes what the customer enters, and then accesses the underlying database application to place the order.
Figure 24.1: A Web order form.
There are several discrete parts of your Intranet ordering and inventory application. The first is the underlying database application, which we've assumed is already in place. You'll need to create the rest of the parts. Your first step should be to create the HTML fill-in forms for each of the major functions of the application. These functions include simple ordering, order status inquiry, and inventory search, so you'll want to build forms for each.
Next, you'll create the CGI/ISAPI programs that underlie your fill-in forms. Although it's possible to write a single script with multiple options, you may want to follow the KISS (Keep it Simple, Stupid!) principle, at least at the outset, by creating separate, simple scripts for each of your forms. Doing so makes debugging substantially easier, and you can always steal from one script when you work on another. It's critical in crafting CGI/ISAPI programs that interface with database applications for you to have an intimate understanding of the way your database accepts and outputs data. As a result, your scripts need to reflect your knowledge of the database itself.
Finally, you'll want to put together an overall Web page (or set of pages) that neatly provides a single, easy-to-access interface to the application. Because HTML markup allows hyperlinks among documents, you can provide a top-level entry point, with branches to each major form accessible with a customer mouse click. Don't forget to provide a way back to the top from each major point in the application.
Let's take a look at the code that creates the form shown in Figure 24.1. As you look at Listing 24.1, you'll notice that HTML markup is shown in all uppercase letters. You should be able to pick out the essential form markup and what it means by comparing the code with its rendering in Figure 24.1. For more information on HTML, see Chapter 5 and Appendix A.
Listing 24.1. The HTML code for the order form is in the file
order.htm on
the CD-ROM.
<HTML><HEAD><TITLE>Order Form</TITLE></HEAD><BODY> <FORM METHOD="post" ACTION="http://intranet.yourco.com/CGI/order.pl"> <H1>Order Form</H1> Type the information in the boxes below, then click <STRONG>submit order</STRONG> to send in your order.<HR> <PRE>Your Name: <INPUT TYPE="text" SIZE=20 NAME=yourname> Phone (Last 4 digits): <INPUT TYPE="text" SIZE=4 NAME="phone"> Employee Badge Number: <INPUT TYPE="text" SIZE=10 NAME="sitepass"> Delivery Location (Bldg/Room#[your initials]): <INPUT TYPE="text" SIZE=15 NAME="location"> Date Required: <INPUT TYPE="text" SIZE=10 NAME="datereq"> Quantity (Number of items desired): <INPUT TYPE="text" SIZE=8 NAME="quantity"> Unit (ea, pk, etc.): <INPUT TYPE="text" SIZE=5 NAME="unit"> Suggested Vendor: <INPUT TYPE="text" SIZE=20 NAME="vendor"> Stock Number (Stores or vendors): <INPUT TYPE="text" SIZE=15 NAME="stockno"> Description: <TEXTAREA NAME="descript" COLS=60 ROWS=2></TEXTAREA> Estimated Cost (per item): <INPUT TYPE="text" SIZE=10 NAME="cost"><BR> Additional Instruction or Information: <EM>If this order exceeds your authorization limit, please indicate your supervisor's name so it can be forwarded electronically for authorization.</EM> <TEXTAREA NAME="moreinfo" COLS=60 ROWS=2></TEXTAREA></PRE> <HR> <INPUT TYPE="submit" VALUE="Submit Order"> <INPUT TYPE="reset" VALUE="Clear Form to Start Over"> </FORM></BODY></HTML>
Despite its length, this form is quite simple, with repeated use of just a few HTML form tags. Several fixed-size fill-in boxes are created using the <INPUT> tag, with the <TYPE> and <SIZE> attributes setting the type of input (text) and the displayed box's size. In addition, the <TEXTAREA> tag is used, with the <COLS> and <ROWS> attributes spelling out the dimensions of the free-form text box. Finally, the special <INPUT TYPE> attributes submit and reset are used for form housekeeping.
Also notice that the <VALUE> tag is used many times. In each case, the word inside the double quotes is used as a name for the information that is entered into the form. You may want to read these into a mental array, as you'll learn more about them later in this chapter, when we consider the CGI scripting that underlies your fill-in forms. For the time being, just think of the <VALUE> tag as a label for each piece of information requested by the form; the labels will be retained and passed to the CGI script when the customer submits the form.
As to the rest of the form, please note:
This form is a good all-purpose form for ordering any number of things. Although this is quite generic, because your Intranet Order and Inventory application is limited to a specific inventory, you may want to give customers access to a predefined set of choices, rather than requiring them to manually type in a text box the name of the item(s) they want to order. This makes customers' lives easier. It also makes the creation of your CGI scripts a lot less troublesome, because customers are not able to make typographical errors in text boxes. Let's look at Figure 24.2, which is a modified version of the form shown previously.
Figure 24.2: A modified order form with a pull-down item selection.
The first thing you'll notice about the modified form is the presence of a drop-down list of available items. Although the example shows a list of just a few office items, you can provide any menu of choices to your customers, who can select the item they want just by clicking on it. The menu is implemented using the HTML <SELECT> tag, with the <OPTION> attribute. You'll want to read the details of the <SELECT> tag and its several attributes in Chapter 5 and Appendix A. Here's the HTML code fragment which sets this up; it replaces the Description entry in the previous HTML document (Listing 24.1):
Description: <SELECT NAME="descript"> <OPTION>File folders <OPTION>Letterhead, 8.5x11 <OPTION>Letterhead, Legal <OPTION>Notepads, 5x7 <OPTION>Notepads, 8.5x11 <OPTION>Paperclips <OPTION>Pencils <OPTION>Pens, ballpoint <OPTION>Pens, felt tip <OPTION>Scotch Tape</SELECT>
This HTML code is part of the file order2.htm on the CD-ROM.
As you can see from Figure 24.2, this is a substantial improvement over the previous form (Figure 24.1). Customers no longer have to manually type the name of the item they want. Instead, they can just select it from the pop-up menu by clicking the item.
You'll also notice the form has been simplified by removing the Suggested Vendor and Estimated Cost text-entry boxes. Presumably, when ordering office supplies, as this form does, you'll get all of them from a single source with known pricing, so you needn't trouble the customer for these two pieces of information. I've also gotten rid of the Stock Number box, because the customer does not need to know it when selecting from the pop-up menu. Finally, data entry fields have been moved up to the same line with the field label to ease right-to-left reading. Already, this first revision of the order form is much more useful. You should resist the urge during form design to ask the user for every imaginable tidbit of data. Users are generally more willing to use a less-cluttered form that is easier to zip through.
There's at least one major remaining problem with this form, however. Suppose customers want to order more than one item at a time. The current form allows only one item to be selected from the pop-up menu. If customers want to order something else, they'll have to reload the form, retype all the identifying information and select the next item. Another attribute to the HTML <SELECT> tag, however, resolves this limitation, with a three-word change to the HTML code. Just change the <SELECT NAME="descript"> line to read like this:
<SELECT NAME="descript" MULTIPLE SIZE=5>
This quick and easy change generates a substantially different-looking order form, as shown in Figure 24.3. As you can see from the product selections already made in Figure 24.3, the customer can now select multiple items from the scrollable menu. (Notice the scrollbar on the right.) The menu created using the <MULTIPLE> attribute is no longer a pop-up, as in Figure 24.2. It is now integrated right into the page, with five lines specified by the <SIZE=5> attribute. This revision appears in a complete HTML order form as order3.htm on the CD-ROM.
Figure 24.3: A modified order form with scrollable item selection.
Note |
You'll also want to look at the <SELECTED> HTML forms attribute, which enables you to specify preset, default selections on pop-up and scrolling menus of the sort used in this form. In addition, as you'll learn from detailed HTML forms documentation, there are a number of other features you can use, including checkboxes, radio buttons, and hidden information useful for session tracking. Hidden information can be useful when the customer needs to fill in more than one form. |
The advantages of the modified form to the customer, with its scrollable menu of choices, are quite obvious. The advantages of the form to you are not so readily apparent, but are possibly even more important.
The main gain, besides the adoration of your customers, is that
your CGI script that will process the form can now be much simpler.
By removing the requirement that customers type the name of the
item(s) they want and replacing it with clickable menu selections,
you've eliminated the potential for customers' typographical and
spelling errors. Because dealing with data entry mistakes is the
bane of programmers everywhere, this change makes your scripting
easier. You now have a set, predictable list of possible entries
for the Description field of the form, and you no longer have
to anticipate and deal in your script with every possible misspelling
or typographical error customers might enter in the form. Also,
a pre-set list of selections reduces the risk of a malicious user
trying to subvert your Intranet's security by sending excessive,
surprise, or dangerous text strings to a CGI/ISAPI program from
a Web form.
Note |
While you're considering the security aspects of your fill-in forms and CGI scripts, you may want to look at the <PASSWORD> tag in HTML forms markup. It works much like an ordinary HTML form text box, but echoes a string of asterisks when customers enter their passwords (to escape the prying eyes of over-the-shoulder onlookers) rather than the actual password. The password entered by the customer is passed on by the form to the CGI or ISAPI program for processing, and the program can verify that customers are who they say they are. Further, your CGI/ISAPI program can use the network hostname of the computer from which the customer is entering information as another verification check by associating customer name, password, and/or computer hostname and checking them against an internal list of allowed matches. Recall that one of the standard CGI environment variables, listed in Chapter 19, "Getting the Most Out of HTML with CGI," is the network hostname of the customer's computer. Finally, you may want to limit access to the form itself, requiring a username and password before bringing up the form in the first place. |
So far, the discussion of HTML forms has focused on pre-set HTML documents containing your forms. These are static HTML documents that you create with a text editor and serve with your Web server, just like other static documents. Your CGI/ISAPI programs, however, can create forms dynamically, and the ability to do so can be important to you. On-the-fly forms creation with a CGI/ISAPI program is done, essentially, by having the program generate valid MIME data type/subtype headers, followed by a stream of HTML markup. In Perl, for example, use the print statement to generate the necessary header and HTML output.
It may be difficult at first to distinguish a reason for preferring a static HTML document over a CGI/ISAPI program (or vice versa) that generates the same fill-in form. In this context, however, recall that Web interfaces to commercial database packages have the capability to make intelligent decisions about what to return to a customer and in what format. CGI/ISAPI programs can do the same thing. One reason you need the power to generate HTML dynamically is that Web browsers differ in their capabilities to render nonstandard HTML markup. Netscape, for example, has developed a set of semi-proprietary extensions to HTML its browsers support; in addition, the company has integrated advanced features of HTML table formatting to its browsers. If you've used another browser, such as ncSA Mosaic, you've no doubt encountered Web pages with such Netscape-isms and found these pages difficult, if not impossible, to view. A growing number of Web pages, however, are based on smart CGI/ISAPI programs that ferret out the name of the user's Web browser and return an HTML document appropriate to the browser. This is quite simple to do, really. One of those standard CGI environment variables, HTTP_USER_AGENT, contains the name and release number of the user's Web browser.
Intelligent CGI/ISAPI program can use the HTTP_USER_AGENT environment variable with each run to identify each customer's Web browser and then return a document or form the browser can display properly. Similarly, you can use other CGI environment variables in your programs to make decisions and provide the appropriate document or form back to the customer. Recall that among these variables is the customer's computer hostname (REMOTE_HOST), numerical IP address (REMOTE_ADDR), and possibly, username (REMOTE_USER), as well as several others. Because your Intranet is by definition a closed group, with access limited to customers inside your organization, you can use predefined lists of users and hostnames in combination with these CGI environment variables to customize the documents, including fill-in forms, returned to customers by your Intranet order and inventory application.
The last couple of paragraphs jumped the gun on this section's subject matter-introducing some advanced CGI/ISAPI programming techniques in the context of dynamically generating custom HTML forms and other documents for different Web browsers. Before we get too far ahead of ourselves, let's take a few steps back and look at the CGI mechanism from a larger perspective and then focus back on your Intranet ordering and inventory application.
Reduced to its most basic level, the CGI mechanism does two things. (ISAPI works essentially the same way.)
For the most part, CGI/ISAPI programs use variables to pass and receive data using standard output and standard input. Each piece of information that a customer enters into a fill-in form is assigned to a variable for easy handling. The values represented by the variables are passed to the back-end program for processing, and results generated by the script are processed by the script and sent back to the customer's browser.
CGI/ISAPI programs can pass the variable information they get from the customer to application packages on your computer system, such as your ordering and inventory relational database package. For example, full-blown Structured Query Language (SQL) queries can be built from Web fill-in forms. Customers enter (or select) SQL search criteria using their Web browser. All the features of HTML forms markup are useful here, including text boxes, pop-up or scrolling menus, checkboxes, radio buttons, and free-form text areas.
The back-end CGI/ISAPI program receives the customer's entries from the form as variables, reformatting the information into a legitimate SQL query. Next, the program passes the query off to the database engine using standard output and waits for a response. When the database engine returns the results of the query, the CGI/ISAPI program receives them as standard input. Recognizing the structure of the database engine's output, the program takes that data and reformats it into HTML. Finally, the HTML-formatted output of the results of the customer's query is returned to his Web browser for viewing.
Along the way, the CGI mechanism provides a handy set of standard environment variables for each transaction. You can use and manipulate these variables in your CGI/ISAPI programs to smarten them up further, allowing them to make decisions about Web-browser capabilities, user authentication, and a long list of other matters. Such decision-making enables you to customize the presentation of your Intranet Ordering and Inventory application.
The very same CGI/ISAPI program might, for example, serve clerical
staff ordering office supplies and scientists ordering lab supplies.
Based on the customer's userid, computer hostname, or other information
from the list of standard CGI environment variables, the form
previously shown (see Figure 24.3) can be dynamically generated,
displaying a different list of available supplies for each customer.
Note |
For more detailed information on CGI programming, check out the ncSA Common Gateway Interface tutorial at http://hoohoo.ncsa.uiuc.edu/cgi/overv iew.html, where you'll find an archive of example scripts. In addition, there's a tremendous list of CGI-related resources, with access to many more example programs, at http://www.yahoo.com/. |
Let's now trace the process of a transaction on your Intranet ordering and inventory application: looking at your forms, how the CGI/ISAPI program processes the data entered into it, and the results.
Having covered the background, let's fill out the sample order form and go over those parts of the HTML markup not analyzed earlier in this chapter. We deferred discussion of the numerous <VALUE> tags in the form's HTML markup. Let's now turn to these items. Take a look at Figure 24.4, which is the same order form as that shown previously but with specific order information filled in. All the data-entry boxes are filled in and a product selected.
Figure 24.4: Completed order form.
Each of the data-entry boxes in the order form is now filled in.
Table 24.1 shows each piece of information the customer entered
in this order form, associated with the HTML <VALUE>
label for that information used in the HTML form.
Label | Value |
yourname | Scott Zimmerman |
phone | 1234 |
sitepass | 9999 |
location | white/333 |
datereq | 3/3/00 |
quantity | 1 |
unit | ea |
descript | File folders |
moreinfo | No signature required for delivery |
The heart of your CGI/ISAPI program for ordering these file folders is the manipulation and use of these nine chunks of information. The information from the fill-in form is passed by the program to the HTTP server, and then to the program, as a set of variables via standard input. (The details differ slightly if you are building or using an ISAPI DLL, but the CGI environment variables are essentially the same.) Your program, then, should expect to receive as standard input these nine discrete pieces of information.
Whether you're writing your CGI application in Perl, Visual Basic, or an ISAPI DLL in C or C++, you'll need to have it accept this information and deal with it. You can do this piece by piece, or by reading the standard input into an array. In the case of ISAPI, the data is essentially already in an array (you'll have a pointer to a memory block). In either event, your program can use these variables to generate a database SQL query/update or a request for a canned database procedure to run.
Finally, the program sends your request, containing the variable
data in SQL format, via standard output, to your database engine
for execution. Alternatively, you can call on the ODBC API and/or
the MFC DAO classes (if you are using Visual C++ 4.x) to interact
with the database with superior efficiency. All of this processing
between the browser, the server, and your CGI application will
happen lightning fast. (You'll notice that the order in Table
24.1 isn't due until after the turn of the century, so there is
no rush on this particular order for a single file folder.)
Note |
C/C++ programmers use the term white space to refer to any number of space, tab, and newline characters. |
Tip |
Because several of these pieces of information are text strings containing white space, with more than one word in them, be sure to use appropriate quoting in your CGI/ISAPI program to handle them properly. |
Your program needs also to expect to get data back from the database engine. Based on the input from the form, which is sent on to the database engine, the CGI/ISAPI program expects a specifically formatted response to the query, containing a specific number of chunks of data. Your program must know precisely how the output of the database engine looks, including record and field separators, to be able to parse it. Again, your program can read this information into an array for easy handling or deal with each piece of data individually. Whichever choice you make, the program now must reformat this variable information into HTML, with appropriate MIME type/subtype header information.
Here's one way in which a Perl script fragment could acknowledge your customer's order:
print "Content-type: text/html\n\n"; print "<HTML><HEAD><TITLE>Order Response</TITLE></HEAD>\n"; print "<BODY><H1>Thanks for Your Order, $yourname</H1><HR>\n"; print "Your order for $quantity \"$descript\" has been placed.\n"; print "It will be delivered to \"$location\" and charged to your account "; print "\"$sitepass\" on or before \"$datereq\"<HR>\n"; print "For information about your order, call the Help Desk\n"; print "</BODY></HTML>\n";
As you can see, the script has echoed back the customer's order essentials with some acknowledgment text and some cosmetic HTML markup to dress up the output.
Now that you've gotten your basic CGI/ISAPI program to process orders, you'll want to add some useful features. There are any number of them, but here are a few ideas to consider. You'll undoubtedly think of others.
You can apply these and other similar extra features as you develop additional forms and CGI/ISAPI programs for other functions in your Intranet order and inventory application. These can provide your customers with the ability to query the database for the status of an order, ask for inventory information on particular items or categories of items, browse the overall catalog of supplies, and the like. You can also create and use fill-in forms that are accessible only to store staff for use in updating inventory and customer account information.
In this chapter, you've applied much of the information you've learned in other chapters of this book to the practical task of creating an Intranet order and inventory application. This combination of HTML forms and CGI/ISAPI programming is a widely useful technique, so you'll want to consider its general lessons in creating other Intranet applications, not limiting your imagination to this particular application. In this chapter, you have focused on:
In Chapter 25, you'll see a similar process of integrating the information and techniques found throughout the book-this time for the creation of boilerplate document libraries.