This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.
|
Designing ASP Files within Visual Basic
Dave Cline |
Ever pull your hair out trying to write an Active Server Page? Dave Cline shows how easy it can be when you use the Visual Basic IDE. |
Looking at an Active Server Pages (ASP) file for the first time, I wondered how I could write complex data applications using such a hodgepodge of languages. VBScript, HTML, SQL, in-process objects, and JScript all in a single file? No thanks, I figured. These languages are hard enough to write and maintain on their lonesome, much less together.
Well, it turns out you can write ASPs in a maintainable, friendly manner in the Visual Basic Integrated Development Environment (IDE). I love the Visual Basic IDE. Visual Basic 4.0 or 5.0, winter or spring, feast or famine, I can get seriously productive within it. But ASP in the Visual Basic IDE? Well, ASP pages are essentially standalone VBScript applications with a few other languages thrown in for good looks and intelligent content. What about HTML and JScript in the Visual Basic IDE? Yes and no. You need to provide for them, but just where and how to store them are some of the tricks you'll learn in this article. To whet your appetite, let's begin by examining a snippet of code. Later on, I'll continue with a discussion of this environment.
Trick 1: Encapsulate all HTML code inside tight, well-named Visual Basic subroutines.
|
<table border=0 width=400 cellpadding=3 cellspacing=0>.
In Figure 1, TableWidth, TableColor, and gintIndent are all defined outside the figure as globals. The first two are set prior to calling the TBStart routine. The third, gintIndent, stores a public integer that controls the indenting of HTML code when it's printed to the browser. Text is a subroutine that writes passed values to the Response object using the Response.Write method. The HTML that gets pumped out of this system looks terrific. Figure 2 gives you a taste of how encapsulation works inside the IDE by comparing Visual Basic statements with their HTML output.
Setup
Now that I've piqued your curiosity, let's perform the
first task, project setup. First, create a new directory on your drive and use Internet Information Server (IIS) to assign it
a virtual directory alias. Make sure to enable the directory's executable rights. You now have a URL of http://127.0.0.1/VirtualDirectory/. I used the TCP loopback address (127.0.0.1) which works on all TCP-enabled machines.
Describing the entire construction of this environment from the ground up would take much more room than I have here. So to speed up my information transfer rate, I'm going to assume that some time soon you will download the code. The download contains not only the ASP and INC code, but also the executable (and its code) for postprocessing.
Trick 2: Name your classes .ASV and your modules .INV.
Notice the .asv and .inv file extensions in Figure 3. These files are actually Visual Basic classes and modules. I've named them this way to facilitate the post-
processing needed to convert these files into full-blooded ASP pages and server-side includes. For more information, see the sidebar.
You can name them this way when you first save them in Visual Basic, or rename them later, changing their names in the Visual Basic project file. You can also just drag them from a file directory of a previous project into the current project window if you're careful with versioning.
Also notice my X files (the X forces them to the bottom of a directory window when listed by name). These are true classes, and are named as such. Note that their names bear a remarkable resemblance to some ASP objects you may have dealt with. This naming convention has its reasons. I don't want to postprocess the X files because they're meant for support only. I rename the classes and modules to .asv and .inv so they're not confused with real classes and modules, and to allow my postprocessor to pick them out of the crowd of files in the directory in which they live.
There are four .asv files in my project: three data-oriented and one index/menu. In addition, there are six classes, five of which are direct equivalents of objects I'll discuss in just a moment. The sixth class, X_Support.cls, combined with my only X-type .bas file provides the instantiation of the five other classes required by my ASP VBScript. The last three files contain subroutines and functions, public constants and variables, common code, and application-specific code to be shared by all the pages within this ASP application.
Trick 3: Create shadow representations of the asp.dll objects.
This is a great time to look at some more code. In Figure 4 I've got some fairly simple ASP code that drives ADO. You might think that I pulled this straight from an ASP page, but this code lives in A01.asv, written completely inside the Visual Basic IDE. With a simple Ctrl+F5, the whole project even compiles. Think about it: compiling ASPs!
If you're familiar with ASP, you'll recognize some old favorites in this code: Server, Request, and Session (Application and Response are represented elsewhere). This snippet came from the Process subroutine, which loads a record's particulars from ADO into Session variables (defined here by constants). The code opens an ADODB connection, then uses it to open a firehose cursor recordset. If the recordset is returned empty, the code saves error messages in a Session-level variable and logs the error to an Application-level log file. If the recordset has one or more records, the code loads a few Session-level variables with values from the database, cleans up after itself, and then uses the application-specific AppRedirect to send the user to the next page. Except for the constants and that last AppRedirect, this code should hold no surprises. I encapsulated the Response.Redirect method so I could add additional control logic if the time came to force a user to a particular page.
The reason I need to clone the ASP objects at all is that they're not available during the writing or compiling of the ASP pages. Even though the reference has been made to the asp.dll, the objects do not become available until they are instantiated within IIS by the ISAPI asp.dll. Shadowing the objects allows me to trick the pages into thinking they have access to the Application, Session, Server, Response, and Request objects when they actually do not.
How I get away with forcing Visual Basic to swallow these ASP constructs is what Trick 3 is all about. I do it by spoofing them as classes that contain all the same methods as the original asp.dll objects. For instance, the X_Server class contains four methodsCreateObject, MapPath, URLEncode, and HTMLEncodeand one property, ScriptTimeout (see Figure 5). You might be misled into thinking the methods must do exactly what the Server object does. This is not the case; they needn't do anything, since they're just placeholders for the real thing.
I'm not going to make an executable out of this project, but I do want the Visual Basic compiler to check all of my variables and constants. For Visual Basic to perform complete compilation, these classes must be instantiated. Otherwise, the code
|
will not have a Session with which to work. This is where X_Support.bas and X_Support.cls come in. X_Support.bas stores object variables that X_Support.cls instantiates with all of my shadow objects when I compile the ASP application. See Figure 6 for clues on how this is done. Other necessary constructs are also tucked away within these shadow objects, such as the implementation of Application, Session, and Request dictionaries as collections. These collections allow me to mimic dictionary functionality by letting me set and retrieve key/value pairs within the class instances. They also provide the ability to preload Session and Request variables for interactive debugging.
Trick 4: Wrap all VBScript routines in Visual Basic lookalikes.
Trick 5: Store common and application routines and constants in server-side includes.
Trick 6: ASP internal file structure.
|
|
These lines instruct the ASP page (after it passes through the postprocessor, removing all the 'asp and 'vb comments) to include the three server-side include files, open up a scripting tag, initialize the constants and variables that I discussed previously, and perform the subroutine titled Route. At the absolute end of the ASV file you will find the closing scripting tag: |
|
Two tags enclose the entire ASP page. Between those two tags you'll find nothing but Visual Basic, comprised of code separated into at least three routines. Sub Route is shown in Figure 8, Sub Paint in Figure 9, and Sub Process in Figure 10. The idea here is that a page should take care of itself. If I'm adding a record to a database, the HTML entry form should be found in the Paint routine. The entry form processing code should be found in the Process routine of the same ASP page. If processing fails, I merely need to call the Paint routine, which repaints the entry form and any error message I choose to display. Route is the first routine called after the page is parsed and executed by the ASP engine. It controls the program's path between the Paint and Process routines (and others if you need them), depending on the state of a Request variable sent back by the Paint routine upon form submission. A typical page transaction might look like Figure 11. |
|
Figure1: A typical page transaction |
Two other routines often used in ASPs I've built are List and Validate. List prints out a table-formatted list of database row contents. Validate contains canned JScript that enables POST form variables to be confirmed for entry and data type prior to submission to the server.
Parting Tips
|
From the April 1998 issue of Microsoft Interactive Developer.