Browsing Ads in the Island Hopper News Sample

Julie MacAller
Microsoft Corporation

January 1999

Introduction

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.

Browsing Ads Overview

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 Components

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

Browsing Ads User Interface

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.

HTML in the Online Classified Advertisement Display Page

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.

Flow of Execution in an ASP Page

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:

  1. The server processes any server-side script and then strips that code out of the page before sending the page to the browser.

  2. The HTML in the page is rendered. Keep in mind, HTML is a streaming language. This means the HTML enters the browser one character at a time, and the browser builds the Web page as the data stream is received. Then the data stream is closed, and—in theory, at least—the HTML cannot be changed. However, DHTML makes it possible to change HTML (using script code) after it's been received by the browser and before it actually displays.

  3. Client-side script is parsed when the page loads. Global or inline scripts are executed immediately; event-handling subroutines or functions, and procedures called by other procedures, are parsed immediately but not executed until triggered by an event or called by a procedure.

Browsing Ads Process

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.

Filling the Category List

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.

  1. The DisplayCategories function creates an instance of the data access component, db_CategoryC.

    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.

  2. The DisplayCategories function calls the ListAll method on the db_CategoryC object.

  3. The ListAll method of the db_CategoryC object builds a SQL command to get the list of current categories from the database, and then it creates a new recordset and sets the CursorLocation property of the recordset to adUseClient, which is required for a disconnected recordset.

    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.

  4. The ListAll method of db_CategoryC executes the SQL command to the database using the Recordset.Open method and supplying the following information:

    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.

  5. The ListAll method of the db_CategoryC object calls the MTS SetComplete method on the MTS ObjectContext object to release any held resources and to signal approval of—but not commit—the transaction, and then it returns the category information to the DisplayCategories function in the AdDisplay.asp file.

    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.

  6. The DisplayCategories function in AdDisplay.asp checks to see if the recordset containing the category information is empty. If the recordset is empty, DisplayCategories displays an error message and exits.

  7. If the recordset is not empty, the DisplayCategories function gets the value of the first category ID and stores it in the m_intFirstCat variable. This value, which is used to determine which ads to display first in the ads list, appears on the right side of the ad display page.

  8. The DisplayCategories function loops through the recordset containing the category information and writes the categories to the CategoryDisplay <DIV> element using the correct HTML tags.

  9. The server puts the value of the first category ID into the SRC attribute on the <IFRAME> tag, which builds the frame where the ads list will be displayed.

Filling the Ads List

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.

  1. The server calls the getCategoryID function in AdsList.asp to retrieve the category ID from the query string. The call uses the VBScript function CInt to convert the category ID to a Variant data type, subtype Integer, so the database can be searched by category ID.

  2. The getCategoryID function passes control back to the server, which checks to make sure the retrieved category ID is valid and then calls the getAdsList function in AdsList.asp to retrieve the ads for the specified category ID from the database.

    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.

  3. The getAdsList function in AdsList.asp creates an instance of the business component, bus_AdC, using the CreateObject method on the Server object, and checks to make sure the object was created correctly by calling a generalized error-handling subroutine, objErrorHandle.

    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.

  4. The getAdsList function in AdsList.asp calls the ListByCategory method on the bus_AdC object, passing in the category ID. ListByCategory retrieves all the ads from the database where the category ID matches the specified category ID.

  5. The ListByCategory method of bus_AdC makes sure the category ID is valid, calls the MTS CreateInstance method on the MTS ObjectContext object to create an instance of the data access component, db_AdC, and then calls the ListByCategory method of db_AdC.

    The db_AdC object is also marked as "requires a transaction," so it also enlists in the current transaction.

  6. The ListByCategory method of db_AdC builds a SQL command to get a list of ads that match the category ID from the database, creates a new disconnected Recordset object, and sets the CursorLocation property of the Recordset to adUseClient.

  7. The ListByCategory method of db_AdC executes the SQL command to the database using the Recordset.Open method.

  8. When the command completes, the ListByCategory method of db_AdC calls the MTS SetComplete method on the MTS ObjectContext object to release any held resources and to signal approval of—but not commit—the transaction, and then it returns the ad information to the ListByCategory method of the bus_AdC object.

  9. The ListByCategory method of bus_AdC calls the MTS SetComplete method on the MTS ObjectContext object to release any held resources and to signal approval of the transaction then returns the ad information to the getAdsList function in AdsList.asp.

  10. The getAdsList function in AdsList.asp checks to make sure the recordset is not empty and then calls the displayAds function to list the ad titles on AdDisplay.asp.

  11. The displayAds function in AdsList.asp loops through the recordset containing the ad information and writes the ads in the adFrame <IFRAME> element on AdDisplay.asp using the correct HTML tags.

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.

For More Information