Julie MacAller
Microsoft Corporation
January 1999
The Island Hopper News sample is an automated classified ads system created by a fictitious company, Island Hopper Publishing, as a test project to evaluate converting the current paper-based weekly newspaper into an online newspaper. The design team consists of the Island Hopper News editor, the Classified Ads and Accounting department heads, and two developers.
This paper describes how the code for browsing ads in Island Hopper fits together and how it works.
Most people are familiar with browsing ads in a paper-based newspaper. All you do is locate the category of ads in which you're interested and read the ads listed in that category. When you translate browsing ads to software, you need to provide a similar structure—a way for users to find a category of interest and a way to access the ads in that category.
Island Hopper News addresses this issue by providing two lists: one of categories and one of ads. Customers or employees click the category in which they are interested, and the ads in that category display in the ads list. External customers use the Web client to browse ads, and Island Hopper Publishing employees can use either the Windows or the Web client. Regardless of client, the user interface for browsing ads is the same.
Browsing ads uses the bus_AdC business component and the db_CategoryC data access component; the bus_AdC component uses the db_AdC component.
These objects expose the following methods:
Object | Methods |
bus_AdC | Delete, GetByID, ListByCategory, ListByCustEmail, ListByCustID, PlaceAd, UpdateAd |
db_AdC | Add, Delete, GetAdCountByCategory, GetByID, ListByCategory, ListByCustEmail, ListByCustID, Update |
db_CategoryC | Add, Delete, GetById, GetByName, GetBySearchString, ListAll, ListByRange, Update |
To browse classified ads, a customer points to the Island Hopper Web site using an Internet browser. After the Web site loads, the customer clicks the Classified Ads link. This link goes to the Browse/Place an Ad page, where the customer can choose whether to browse or place classified ads. The customer clicks the Browse an Ad link, which goes to the Online Classified Ads Display page (AdDisplay.asp), shown in the following figure.
This page lists the ad categories on the left and the titles of ads in that category on the right. Customers click a category to display a list of ad titles in that category and click an ad title to view the full text of the ad.
The ad categories list is a <DIV> element called CategoryDisplay. The categories themselves are retrieved from the database, and a Microsoft® Visual Basic Scripting Edition (VBScript) subroutine loops through the recordset and writes each category name into the <DIV> using a <SPAN> tag.
The ads list is an inline floating frame element (<IFRAME>) called adFrame. The ads that correspond to the selected category are retrieved from the database, and a VBScript subroutine loops through the recordset and writes each ad title into the <IFRAME> using a <SPAN> tag.
The ASP pages in the Island Hopper News application typically contain a mixture of client-side script, server-side script, and HTML. In a page with such a mixture of technologies, you might wonder what gets executed first. Here's the order:
From a developer's point of view, there are two main parts to the browsing ads process:
Each of these parts is discussed in this white paper.
This step fills the list of categories on the left side of the ad display page by extracting the current list of categories from the database and writing the list to the <DIV> element called CategoryDisplay.
The processing in this step is carried out by the DisplayCategories function in the AdDisplay.asp file. The following figure illustrates the interaction between the AdDisplay.asp file, the db_CategoryC data access component, and the database.
The following steps summarize the process.
The db_CategoryC component is marked as "requires a transaction," so it enlists in the current transaction, which started when the server started processing AdDisplay.asp.
A disconnected recordset is a recordset in a client cache that no longer has a live connection to the server. If you need to do something with the original data source, such as updating data, you need to re-establish the connection. Using disconnected recordsets minimizes use of database connections, which helps make an application more scalable.
The file DSN is a text file that contains the data source, user ID, and password needed for accessing the database. Using a file DSN means you can modify the data source or access information as necessary without making any source code changes. File DSNs do incur a performance hit, but they provide access to multiple users and are easily transferable from one server to another.
Note In your own applications, you will probably want to use user or system DSNs or specify the connect information in a connect string to avoid the performance penalty of using a file DSN.
The adOpenKeyset property specifies a keyset cursor. With a keyset cursor, you can see data changes made by other users. However, you can't see records that other users add, and you can't access records that other users delete.Disconnected recordsets require either adOpenStatic or adOpenKeyset for the cursor type.
The adLockReadOnly property locks the records as read-only. You can view the data, but you cannot change it.
The adCmdText constant indicates the data provider should evaluate the value of the strSQL variable as a textual definition of a command. This constant provides a performance benefit, because ADO doesn't have to figure out what the value of strSQL represents before executing it.
Note Why is a transaction used here? It's true that you don't usually need transactions for database read operations. It's also true that the transaction settings on the Island Hopper components weren't optimized; all the Island Hopper business and data access components are marked as "requires a transaction," even if they are sometimes used in operations that don't require a transaction.
However, in ASP, the only transaction settings that really make sense are "requires a transaction" and "not supported," since the scope of the transaction is one page. Either the page uses transactions or it does not. If the components used on a page (for example, bus_AdC and db_CategoryC) are marked as requiring transactions and the ASP page is not transactional, two separate transactions would be created for the call into bus_AdC and the call into db_CategoryC, which would impact performance.
In the Island Hopper News sample, pages that use any Island Hopper components are marked transactional, because all the Island Hopper components themselves are marked transactional. This way, all the work of the page is done within a single transaction.
In this step, the browser renders the inner ad frame (IFRAME ID=adFrame). As part of the rendering process, the browser calls AdsList.asp to fill the frame with the list of ads, using a query string to pass the first category ID to AdsList.asp.
The processing in this step is carried out by the getCategoryID, getAdsList, and displayAds functions in the AdList.asp file. The following steps summarize the process.
If the retrieved category ID is not valid, the server places an error message in the HTML stream and sends the page to the browser.
The objErrorHandle subroutine finds errors in object creation. It checks the value of Err.Number and writes an error message if the value of Err.Number is anything other than zero. Unlike AdDisplay.asp, which creates only one object, AdsList.asp creates a number of objects, so it's much easier to store the error-handling code in one place and call it when necessary.
The bus_AdC component is marked as "requires a transaction," so it is enlisted in the current transaction—the one that began when the server started processing AdDisplay.asp.
The db_AdC object is also marked as "requires a transaction," so it also enlists in the current transaction.
After filling the category and ads lists, the server commits the transaction and sends the AdsList.asp page to the browser, which parses the HTML and client-side scripts and then loads the page. Once the AdsList.asp page is loaded, AdDisplay.asp continues rendering the HTML in the page. Then the browser loads the AdDisplay.asp page, triggering the start() function.