You are on page 1of 64

Active Server Pages Tutorial

Microsoft Corporation
Updated December 27, 2000

Summary: This two-module tutorial provides a step-by-step introduction to several ASP features. The
tutorial shows how to build sample applications and demonstrates key concepts you'll need to
understand when developing your own ASP pages. (11 printed pages)

Welcome to the Active Server Pages (ASP) tutorial. If you are new to Microsoft® Internet Information
Services (IIS), this introduction provides necessary information about tutorial directory structure and
permission issues. The two tutorial modules show you how to build sample applications, while
demonstrating key concepts you'll need to understand when developing your own ASP pages. We
suggest you work through each lesson in Module One before starting Module Two.

This article contains the following sections:

 Introduction. This section defines what ASP is, how it works, and other technologies that can be
used in conjunction with ASP to create active content on your Web site. It also describes the
directory structure you should use for the tutorial and security considerations that may affect
your ability to run the tutorial.

 Module One. This module introduces the creation of an ASP page, and focuses on the collection
and transfer of data. It contains the following lessons:

 Write and Run an ASP Page. Describes how to use Visual Basic® Scripting Edition
(VBScript) and HTML tags.

 Send Information by Using Forms. Shows how to use forms to send information.

 Create a Guest Book. Shows how to create a sign-in book on your ASP page for visitors
to your Web site.

 Display an Excel Spreadsheet in ASP. Explains how to display an Excel spreadsheet on an


ASP page.

 Module Two. This module contains the following lessons:

 Rotate Information Randomly. Shows how to rotate ads on your Web page randomly.

 Record Traffic with a Page Counter. Demonstrates the use of a page counter to track the
number of hits a page receives.

Introduction
Microsoft® Active Server Pages (ASP) is a server-side scripting technology that can be used to create
dynamic and interactive Web applications. An ASP page is an HTML page that contains server-side
scripts that are processed by the Web server before being sent to the user's browser. You can combine
ASP with Extensible Markup Language (XML), Component Object Model (COM), and Hypertext Markup
Language (HTML) to create powerful interactive Web sites.

Server-side scripts run when a browser requests an .asp file from the Web server. ASP is called by the
Web server, which processes the requested file from top to bottom and executes any script commands.
It then formats a standard Web page and sends it to the browser.

It is possible to extend your ASP scripts using COM components and XML. COM extends your scripting
capabilities by providing a compact, reusable, and secure means of gaining access to information. You
can call components from any script or programming language that supports Automation. XML is a
meta-markup language that provides a format to describe structured data by using a set of tags.

As you work through the lessons in each module, save your work in the C:\Inetpub\Wwwroot\Tutorial
directory to view the content on your Web site. If you did not customize your installation of IIS,
C:\Inetpub\Wwwroot was created as the default home directory. To load and run the tutorial samples,
you must have administrator privileges on the computer running IIS. The default IIS security settings
should allow you to run the tutorial, but you may need to change your security settings on the directory
if you encounter access violations. See the product documentation for more information about IIS
security settings.

Module One

This module explains how to create ASP pages (.asp files) that use the fundamental features of HTML,
ASP, and VBScript. This module includes the following lessons:

 Write and Run an ASP Page. Describes how to use Visual Basic® Scripting Edition (VBScript) and
HTML tags.

 Send Information by Using Forms. Shows how to display forms on an HTML page.

 Create a Guest Book. Uses forms to gather information from visitors, store the information in a
database, and display the database contents in a Web page.

 Display an Excel Spreadsheet in ASP. Explains how to display an Excel spreadsheet in a Web
page.

Write and Run an ASP Page

The best way to learn about ASP pages is to write your own. This lesson covers VBScript syntax and
coding samples. To create an ASP page, use a text editor to insert script commands into an HTML page.
Saving the page with an .asp file name extension tells the Web server how to process the script
commands. To view the results of a script, request the page using a Web browser. VBScript is the default
scripting language for ASP, and most of the examples in the tutorial are scripted in VBScript.

In HTML, you use brackets as delimiters around the tags:

Copy

<example>

In VBScript, you use the percent sign with brackets as delimiters around the tags:

Copy

<%example%>

You can put many tags inside one pair of VBScript delimiters:

Copy

<%example, samples%>

Example 1

This example displays the words "Hello World". To run this example, cut and paste it into an empty file
and save it in the C:\Inetpub\Wwwroot\Tutorial directory as Example1.asp. Make sure to save your file
with an .asp extension. Some text editors automatically change the file name extension to .txt when the
Text Document option is selected in the Save dialog box. To prevent this, select the All Files(*.*) option.
Exit your text editor as the server may not be able to display an HTML page that is open in a text editor.
View your page with your browser by typing http://<Your Server Name>/Tutorial/Example1.asp in the
address bar.

When running Example 1, the page is processed by the Web server in the following sequence:

1. Assigns the text "Hello World" to the variable FirstVar.

2. Uses HTML to make an HTML page.

3. Uses <%FirstVar%> to print out the value of the variable FirstVar.

4. Ends the HTML page.

Copy
<%@ Language=VBScript %>

<html>

<head>

<title>Example 1</title>

</head>

<body>

<%

FirstVar = "Hello world!"

%>

<%=FirstVar%>

</body>

</html>

Example 2

This example incorporates a FOR loop in the ASP page. The FOR loop is a statement that prints "Hello
World" 10 times. To create Example 2, use the file from Example 1 and add the FOR loop code as shown
in the following code sample. Save the file as Example2.asp. View it in your browser.

Copy

<%@ Language=VBScript %>

<html>

<head>

<title>Example 2</title>

</head>

<body>

<%

FirstVar = "Hello world!"


%>

<%FOR i=1 TO 10%>

<%=FirstVar%>

<%NEXT%>

</body>

</html>

Example 3

In this example, a time stamp is added to the ASP page. The word time is a function; it is a predefined
VBScript function variable containing the current time. There are more than 90 functions in VBScript.
Add the code for time shown in the following code sample to Example2.asp and save it as Example3.asp.
View it in your browser.

Copy

<%@ Language=VBScript %>

<html>

<head>

<title>Example 3</title>

</head>

<body>

<%

FirstVar = "Hello world!"

%>

The time is: <%=time%> <BR>

<%FOR i=1 TO 10%>

<%=FirstVar%>

<%NEXT%>

</body>
</html>

Example 4

This example displays the message "Good Morning Everyone" if the hour is between 4:00 A.M. and 6:00
P.M. It displays the message "Good Night Everyone" if the hour is between 6:00 P.M. and 4:00 A.M. Add
the IF THEN statement in the code shown below to Example3.asp and save it as Example4.asp.

Copy

<%@ Language=VBScript %>

<html>

<head>

<title>Example 4</title>

</head>

<body>

<%IF Hour(time)>18 OR Hour(time)<4 THEN%>

Good Night Everyone.

<%ELSE%>

Good Morning Everyone.

<%END IF%>

</body>

</html>

Send Information by Using Forms

A common use of intranet and Internet server applications is to process a form submitted by a browser.
With ASP, you can embed scripts written in VBScript directly into an HTML file to process the form. ASP
processes the script commands and returns the results to the browser. In this lesson, you create an
HTML page that displays various elements of an HTML form. Later in this module, you use this
knowledge of forms to build a guest book application on your Web site.

This lesson contains the following examples:


 Button example. Displays selection buttons in the form.

 Text example. Displays text boxes in the form.

Button example

In this example, there are three input lines that use "buttons," and two default buttons-RESET and
SUBMIT. The Post method is used to send data from the client browser to the Web server. Open your
text editor, create a new file, and paste in the following code. Save the file as Button.htm and view the
page in your browser.

Copy

<html>

<head>

<title>Button Form</title>

</head>

<body>

<FORM NAME="Button Example" METHOD="POST" ACTION="tutorial/button.htm">

Computer Programming Experience:

<P>

<INPUT TYPE="button" NAME="choice" VALUE="Less than 1">Less

than 1 year.<BR>

<INPUT TYPE="button" NAME="choice" VALUE="1 to 5">1-5 years.<BR>

<INPUT TYPE="button" NAME="choice" VALUE="More than 5">More

than 5 years.

</P>

<P><INPUT TYPE="reset" VALUE="Clear Form">

<INPUT TYPE="submit" VALUE="Submit">

</P>

</form>

</body>
</html>

Text example

In this example, you create text fields in a form. Open a new file in your text editor, paste in the
following code, and save the file as Text.htm:

Copy

<html>

<head>

<title>Text Form</title>

</head>

<body>

<FORM NAME="Text Example" FORM METHOD="POST" ACTION="tutorial/text.htm">

<TABLE>

<TR>

<TD ALIGN="RIGHT" VALIGN="MIDDLE">Name?

<TD ALIGN="LEFT">

<INPUT TYPE="text" NAME="name" VALUE=""

SIZE="20" MAXLENGTH="150">

<TR>

<TD ALIGN="RIGHT" VALIGN="MIDDLE">Company?

<TD ALIGN="LEFT">

<INPUT TYPE="text" NAME="company" VALUE=""

SIZE="25" MAXLENGTH="150">

<TR>

<TD ALIGN="RIGHT" VALIGN="MIDDLE">

Email Address?
<TD ALIGN="LEFT">

<INPUT TYPE="text" NAME="email" VALUE=""

SIZE="25" MAXLENGHT="150">

</TABLE>

<INPUT TYPE="reset">

<INPUT TYPE="Submit" NAME="Submit" VALUE="Submit">

</form>

</body>

</html>

Create a Guest Book

This lesson describes how to develop a guest book application. Guest books allow visitors to your site a
chance to give you feedback. Information such as the visitor's name, e-mail address, and comments can
be available to you.

Create the guest book database

You must first create an Access database called Guestbook.mdb and save it in the
C:\Inetpub\Wwwroot\Tutorial directory. The database must have the fields with the properties
described in the following table.

Field Name Data Type and General Properties

ID AutoNumber, Field Size=Long Integer, New Values=Increment,


Indexed=Yes(No Duplicates)

TB1 Text, Field Size=255, Required=No, Allow Zero Length=Yes, Indexed=No

TB2 Text, Field Size=255, Required=No, Allow Zero Length=Yes, Indexed=No

TB3 Text, Field Size=255, Required=No, Allow Zero Length=Yes, Indexed=No

TB4 Text, Field Size=255, Required=No, Allow Zero Length=Yes, Indexed=No

MB1 Memo, Required=No, Allow Zero Length=Yes

After you create the database, you need to create a data source name (DSN) connection to the database
so your ASP application can interact with it. The DSN must be created on the Web server that is running
the ASP application. If you move the ASP application to a different Web server, you have to re-create the
DSN on the new Web server. The following procedure describes how to create a DSN on Windows NT
and Windows 2000.

1. In the ODBC Data Source Administrator, select the ODBC icon.

2. Select File DSN.

3. Select Add, select Microsoft Access Driver, and click Next.

4. Type in a descriptive name for your file DSN (Guestbook) and click Next.

5. Click Finish, click Select, specify the location of the database file, and select OK.

6. Click OK twice. After you specify the location of the database file, the ODBC Data Source
Administrator creates a file DSN for it.

Now that you have created the database and the DSN, paste the following code into a file named
Guestbook.asp and place it in the C:\Inetpub\Wwwroot\Tutorial directory.

Copy

<% @Language=VBScript %>

<html dir=ltr>

<head>

<TITLE>Guest Book</TITLE>

</head>

<body bgcolor="#FFFFFF" text="#000000">

<%

IF request.form ("Message")="True" THEN

strTB1=request.form("To")

strTB2=request.form("EMailAdd")

strTB3=request.form("CC")

strTB4=request.form("Subject")

strMB1=request.form("Memo")

IF strMB1 = "" THEN


iLenMB1=255

ELSE

iLenMB1 = Len(strMB1)

END IF

'Connects to the Access driver and Access database in the Inetpub

'directory where the database is saved

strProvider = "Driver={Microsoft Access Driver (*.mdb)};

DBQ=C:\Inetpub\Wwwroot\Tutorial\guestbook.mdb;"

'Creates an instance of an Active Server component

set objConn = server.createobject("ADODB.Connection")

'Opens the connection to the data store

objConn.Open strProvider

'Instantiate Command object and use ActiveConnection property to

'attach connection to Command object

set cm = Server.CreateObject("ADODB.Command")

cm.ActiveConnection = objConn

'Define SQL query

cm.CommandText ="INSERT INTO Guestbook (TB1,TB2,TB3,TB4,MB1)

VALUES (?,?,?,?,?)"

'Define query parameter configuration information for guestbook fields

set objparam=cm.createparameter(, 200, , 255, strTB1)

cm.parameters.append objparam

set objparam=cm.createparameter(, 200, , 255, strTB2)

cm.parameters.append objparam

set objparam=cm.createparameter(, 200, , 255, strTB3)


cm.parameters.append objparam

set objparam=cm.createparameter(, 200, , 255, strTB4)

cm.parameters.append objparam

set objparam=cm.createparameter(, 201, , iLenMB1, strMB1)

cm.parameters.append objparam

cm.execute

response.write("Thank you!")

ELSE%>

<h1>Guestbook</h1>

<!--Post information to Guestbook form -->

<form name=guestbook.asp action="guestbook.asp" method="POST">

<p>To</p>

<p><input type="Text" name="To"></p>

<p>Email Address</p>

<p><input type="Text" name="EmailAdd"></p>

<p> CC</p>

<p><input type="Text" name="CC"></p>

<p>Subject</p>

<p><input type="Text" name="Subject"></p>

<p>Message</p>

<p><textarea name="Memo" rows=6 cols=70></textarea></p>

<input type="HIDDEN" name="Message" value="True">

<input type="submit" value="Submit information">

</form>

<%End if%>
</body>

</html>

View the database in a browser

Using a database to collect information left by visitors is a safe and simple way to make your Web site
more useful. Once information is entered in a database, you can either open the database in the
application in which it was originally created, or you can use a Web page containing another script to
view and edit the data. The following is a script that allows visitors to view and edit your database. To
learn more about how to limit access to resources on your site, see "NTFS Security, Part 1: Implementing
NTFS Standard Permissions on Your Web Site," available at
http://www.microsoft.com/technet/iis/ntfssec.asp.

Copy

<% @Language=VBScript %>

<html dir=ltr>

<head>

<title>View Guest Book</title>

</head>

<body bgcolor="#FFFFFF" text="#000000">

<%

'This section makes it possible for visitors to sort the data in the

columns in ascending order.

if request.form("sort")<> "" THEN

StrSort=request.form("sort")

ELSE

StrSort="TB1 ASC"

END IF

strQuery="SELECT * FROM Guestbook ORDER BY " &StrSort

'Database path statement describing the driver to use and the


path to the desired database.

strProvider = "Driver=Microsoft Access Driver (*.mdb);


DBQ=C:\Inetpub\Wwwroot\Tutorial\guestbook.mdb;"

IF Request("ID") <> "" THEN

strIDNum=Request("ID")

'Creates an instance of an Active server component

set objConn = server.createobject("ADODB.Connection")

'Opens the connection to the data store

objConn.Open strProvider

'Instantiate Command object and use ActiveConnection property to

'attach connection to Command object

set cm = Server.CreateObject("ADODB.Command")

cm.ActiveConnection = objConn

'Define SQL query

cm.CommandText = "DELETE FROM Guestbook WHERE ID = " &strIDNum

cm.Execute

END IF

'Instantiate a Recordset object and open a recordset using

'the Open method

Set rst = Server.CreateObject("ADODB.recordset")

rst.Open strQuery, strProvider

%>

<h1>Guest Book</h1>

<form name=viewdb.asp action=viewdb.asp method=post>

<table border=1 cellspacing=3 cellpadding=3 rules=box>

<%
ON ERROR RESUME NEXT

IF rst.EOF THEN

Response.Write "There are no entries in the database."

ELSE%>

<tr>

<%

'Deletes rows from the database, this cannot be undone

Response.Write "<td width=200><center>Delete Record</center></td>"

FOR i = 1 to rst.Fields.Count -1

Response.Write "<td width=200><input name=sort value=" & rst(i).Name

& " type=submit></td>"

NEXT

WHILE NOT rst.EOF %>

<tr>

<%

Response.Write "<td align=left valign=top bgcolor='#ffffff'>

<a href=viewdb.asp?id=" & rst(0) & ">Delete</a></td>"

FOR i = 1 to rst.fields.count - 1

Response.Write "<td align=left valign=top bgcolor='#ffffff'>" & rst(i)

&"</td>"

NEXT

rst.MoveNext

WEND

END IF

%>
</table>

</form>

</body>

</html>

Display an Excel Spreadsheet in ASP

This lesson demonstrates a technique that can be used to display a Microsoft Excel spreadsheet in a
Web page. There are several standard server components supplied with IIS. One of these is the ActiveX®
Data Objects (ADO) component, which is used as a connection mechanism to provide access to data. In
the database lesson earlier, we used ADO. We use it again here to show you how to view and edit a
spreadsheet with a Web browser.

To prepare your Excel spreadsheet for display in an Active Server Page:

1. Create a spreadsheet using either Excel 98 or Excel 2000 and save it as ASPTOC.xls in the
C:\Inetpub\Wwwroot\ directory.
Note: Do not include any special formatting or column labels when creating the spreadsheet.

2. Highlight the rows and columns on the spreadsheet that you want displayed in the Web page.

3. On the Insert menu, choose Name, and select Define.

4. If there are any names listed, select them and select Delete.

5. Type a name for the workbook, select Add, and select OK.

To display the spreadsheet in a Web page, you must create a DSN for the spreadsheet. The process is
the same as it was for the database lesson earlier in this module. The only difference is that you must
select the {Microsoft Excel Driver (*.xls)} option for the DSN.

Once you have created the spreadsheet and named the table in the spreadsheet, and also created a DSN
for the spreadsheet, you are ready to create the page that displays the contents. Paste the following
code into a new file and name it ASPTOC.asp. Save it in the C:\Inetpub\Wwwroot\Tutorial directory and
view the page in your browser.

Copy

<%@Language=VBScript %>

<html>

<head>
<title> Displaying An Excel Spreadsheet in an Web Page </title>

</head>

<body bgcolor="#FFFFFF" text="#000000" >

<h1>ASP Table of Contents</h1>

<%

'Creates an instance of an Active Server Component

Set oConn = Server.CreateObject("ADODB.Connection")

'Connects to the Excel driver and the Excel spreadsheet

'in the directory where the spreadsheet was saved

strConn = "Driver={Microsoft Excel Driver (*.xls)}; DBQ=C:\Inetpub\Wwwroot\Tutorial\ASPTOC.xls;"

'Opens the connection to the data store

oConn.Open strConn

'Selects the records from the Excel spreadsheet

strCmd = "SELECT * from `ASPTOC`"

Set oRS = Server.CreateObject("ADODB.Recordset")

'Opens the recordset

oRS.Open strCmd, oConn

'Prints the cells and rows in the table

Response.Write "<table border=1><tr><td>"

'Gets records in spreadsheet as a string and prints them in the table

Response.Write oRS.GetString (, , "</tr><td>", "</td></tr><tr><td>",

NBSPACE)

%>

</body>

</html>
Module Two

This module explains how to develop an ASP page that delivers services useful in e-commerce. This
module includes the following lessons:

Rotate Ad Information. Randomly rotate ads on your Web page.

Redirect Users from Ad Links. Redirect browsers to advertisers' sites when users click on an ad image.

Count Page Hits. Track the number of times users request a page.

Rotate Ad Information

Advertising is big business on the Web. This lesson explains how to take advantage of the Ad Rotator
component installed with ASP by describing how to use this component to rotate advertisements on
your Web pages. The Ad Rotator component selects an advertisement for your Web page each time the
user refreshes or loads the Web page. Two files are required to set up the Ad Rotator component: an Ad
Rotator Include file and an ad images data file. By setting up these two files, this component can be
called by any ASP page on your site. Changes to the ad parameters are not done on all the sites
containing the ad, but to the ad images data file. This saves lots of time if the ad appears on numerous
pages within your Web site.

This lesson explains how to:

Write an Ad Rotator Include File. Creates the ad-image links on any page that calls this file.

Create an Ad Image Data File. Specifies global ad-display data and information specific to each ad.

Test the Ad Rotator. Uses an ASP page that calls the Ad Rotator logic Include file and the image data file
to display and rotate ads.

Write an Ad Rotator Include file

Include files are used to store information that will be used by more than one ASP or HTML file. By
creating an Ad Rotator Include file, when changes need to be made to specific information, you only
need to change the information in one location. This lesson will guide you in creating an Ad Rotator
Include file containing a function named getAd(). This function randomly selects ads to display on your
ASP pages. You can call this file from within any ASP page intended to display the rotated ads. When you
test calling the Include file from an ASP page (see Test the Ad Rotator), you will use some images from
Microsoft.com for ad images.

Open a new file in your text editor, paste in the following script, and save the file as Adrotatorlogic.inc:

Copy
<%

Function getAd()

Dim load

'Create an instance of the AdRotator component

Set load=Server.CreateObject("MSWC.AdRotator")

'Set the target frame, if any. This is the frame

'where the URL will open up. If the HTML page does

'not find the target name, the URL will be opened

'in a new window.

load.TargetFrame = "Target = new"

'Get a random advertisement from the text file.

getAd = load.GetAdvertisement("adimagedata.txt")

End Function

%>

Create an ad images data file

An ad images data file is created to provide information about the ads to be displayed. By placing the
data in one text file, when changes need to be made, you only need to change the data in one location.
The ASP page (with the logic in the Include file) sends data in the ad images data file to the Ad Rotator
component. The component then selects an ad for display.

The data file is divided into two sections that are separated by an asterisk (*). The first section provides
information common to all the ads to be displayed. The second section lists data relevant to each ad.
 The following outlines the structure of an ad images data file:

 REDIRECTION. URL, the path and name of the ASP file that redirects browsers that
select ad images.

 WIDTH. The width of ad images in pixels. Default is 440.

 HEIGHT. The height of ad images in pixels. Default is 60.

 BORDER. The border thickness around ad images. Default is 1.

 *. Separates the first section from the second section.

 AdURL. Virtual path and filename of the image file containing the advertisement.

 AdHomeURL. URL to jump to when this link is selected. To indicate there is no link, use a
hyphen.

 Text. Text to display if browser does not support graphics.

 Impressions. An integer indicating the relative weight, or probability, that this ad will be
selected for display. For example, if two ads were displayed, one with an impression of 3
and the other with 7, then the one with 3 would have a 30 percent probability of being
selected, while the other would have a 70 percent probability.

Open a new file in your text editor, paste in the following script, and save the file as Adimagedata.txt:

Copy

REDIRECT adrotatorredirect.asp

WIDTH 250

HEIGHT 60

BORDER 0

* ' separates the general data from the image information

images/windows_logo.gif

http://www.microsoft.com/windows

Microsoft Windows

images/office_logo.gif
http://www.microsoft.com/office

Office 2000

Test the Ad Rotator

To test the system, you will need an ASP page that calls the Ad Rotator Include file and the ad images
data file, and then displays the ads. First, you will need test ad images stored on your site.

Acquire and store the ad images as follows:

1. Create a directory named Images in the tutorial folder: C:\Inetpub\Wwwroot\Tutorial\Images.

2. Download the Office logo file, available at


http://www.microsoft.com/office/images/office_logo.gif, from the Microsoft Office Web site,
and save it as Office_logo.gif in C:\Inetpub\Wwwroot\Tutorial\Images.

3. Download the Windows logo file, available at


http://www.microsoft.com/windows/images/bnrwinfam.gif(, from the Microsoft Windows Web
site, and save it as Windows_logo.gif in C:\Inetpub\Wwwroot\Tutorial\Images.

Open a new file in your text editor, paste in the following script, and save the file as Displayad.asp:

Copy

<%@ Language="VBScript" %>

<!--Call the Include file, which in turn -->

<!--calls the ad images data text file-->

<!--#include file="adrotatorlogic.inc"-->

<html>

<head>

<title>Test Ad Display Page</title>

</head>

<body>

<h1>Test Ad Display Page</h1>


<!--Display the ad banner-->

<p><%=getAd()%></p>

<p>The space above should contain an image displaying either the

Microsoft Windows family logo or the Microsoft Office

family logo.</p>

<ul>

<li type="disc">This indicates that Displayad.asp, Adrotatorlogic.inc,

and Adimagedata.txt are working together to correctly display the

images.</li>

<li type="disc">Repeatedly refreshing the page should result in the

Windows and Office logos displaying in random order.</li>

<li type="disc">After you save Adrotatorredirect.asp, clicking on the

displayed image should cause a new window to open, displaying the

home page corresponding to the displayed logo.</li>

<li type="disc">After you add the hit counter script to this page,

under "Statistics" you should see the number of page hits since

the script was added.</li>

</ul>

<br><br><br><br><br>

<h3>Statistics</h3>

<% Set pageCount = Server.CreateObject("MSWC.PageCounter") %>

<!--Increment the counter-->

<% pageCount.PageHit %>

<p>You are visitor number <% =pageCount.Hits %> to this Web page.</p>

</body>
</html>

Redirect Users from Ad Links

When a user clicks the ad, the browser appends a query string to the request to the server. Then, the
server directs the user's browser to the ad's URL.

Open a new file in your text editor, paste in the following script, and save the file as
Adrotatorredirect.asp:

Copy

<%@Language=VBScript %>

<html>

<head>

<title>Redirection Page</title>

</head>

<body>

<%

'Set the response buffer on

Response.Buffer = True

Dim lsURL

'Obtain the URL from the query string

lsURL = Request.QueryString("URL")

'Clear the response and redirect to URL

Response.Clear()

Response.Redirect(lsURL)

%>

</body>

</html>
To check your work, use Displayad.asp. When you click on an ad, you should see a new window
displaying an appropriate ad-related Web page.

Count Page Hits

It is important to know how many hits your Web pages get. This data helps determine how changes to
your Web site may affect your customers' viewing habits. More importantly, it provides useful insight as
to how customers are navigating through your site and where ads should be placed. Sites with high
trafficking have higher advertisement prices associated with them. The data gathered from a page hit
counter provides you with trafficking information to begin negotiating advertisement prices for your
Web pages.

The Page Counter component uses an internal object to record page hit-count totals for all pages on the
server. At regular intervals, this object saves all information to a text file so that no counts are lost due
to power loss or system failure. The Page Counter component uses the following three methods:

 Hits(). This displays the number of hits for a Web page. The default is the current page.

 PageHit(). This increments the hit count for the current page.

 Reset(). This resets the hit count for a page to zero. The default is the current page.

An in-use sample of this script can be seen at the bottom of the Displayad.asp script. To place a page hit
counter on a Web page, place the following script where you want the counter displayed on the page:

Copy

<% Set pageCount = Server.CreateObject("MSWC.PageCounter") %>

<% pageCount.PageHit %>

You are visitor number <% =pageCount.Hits %> to this Web site.

ASP from A to Z

Nancy Winnick Cluts


Developer Technology Engineer
Microsoft Corporation

October 22, 1998


Contents
Introduction
What ASP Is
How ASP Works
ASP from A to Z
Bibliography

Introduction
There's lots of helpful information about Active Server Pages (ASP) available on this site and
other sites. If you have plenty of time to search for the information, you can find answers to most
of your questions. But if you want to find out what tools you can use to debug ASP or how to
handle errors, you need to do some digging. This article provides an easy way to find
information that pertains to ASP, including a short definition of what ASP is, how ASP works,
and an alphabetical list of terms and tips that relate to ASP. In the A-to-Z list, you will see a brief
description as well as pertinent links to more detailed information (when that information is
available). This article is meant to be a "living" document. That means that I plan on updating it
with new tips and removing tips that no longer apply. If you are an ASP developer and have a
"juicy" tip, send it to me. If I publish it here, you'll get credit and the everlasting gratitude of
throngs of other ASP developers.

What ASP Is
Active Server Pages is a programming environment that provides the ability to combine HTML,
scripting, and components to create powerful Internet applications that run on your server. If you
are already creating Web sites that combine HTML, scripting, and some reusable components,
you can use ASP to glue these items together. You can create an HTML interface for your
application by adding script commands to your HTML pages and you can encapsulate your
business logic into reusable components. These components can be called from script or other
components.

How ASP Works


When you incorporate ASP into your Web site, here's what happens:

1. The user brings up a Web site (like MSDN Library) where the default page has the extension
.asp.
2. The browser requests the ASP file from the Web server.
3. The server-side script begins to run with ASP.
4. ASP processes the requested file sequentially (top-down), executes any script commands
contained in the file, and produces an HTML Web page.
5. The Web page is sent to the browser.

Because your script runs on the server, the Web server does all of the processing and standard
HTML pages can be generated and sent to the browser. This means that your Web pages are
limited only by what your Web server supports. Another benefit of having your script reside on
the server is that the user cannot "view source" on the original script and code. Instead, the user
sees only the generated HTML as well as non-HTML content, such as XML, on the pages that
are being viewed.

ASP from A to Z
This section contains a list of terms and tips to help you understand ASP. They are listed in
alphabetical order. Scroll down to the topic that interests you or click the letter in the alphabet
below to jump down to the section containing the topic. I cribbed, er, I mean, compiled these tips
and definitions from a number of sources, including technical articles (listed in the bibliography
below), Knowledge Base articles, and a beta version of the Microsoft® Internet Information
Server (IIS) 5.0 documentation (I'm so lucky!).

A      B      C      D      E      F      G      I      J      L      M      O      P      Q      R      S      T      V
W      X      

ADO

Active Data Objects (ADO) provides a programming model for an OLE-DB data source. It is the
database model that ASP uses; however, ASP can use other database access mechanisms. ADO
supports the following installable objects, which are often used in ASP files: Command,
Connection, Recordset, Field, and Error. Refer to the ADO Web site at
http://www.microsoft.com/data/ado/ for more information than you can shake a stick at.

Applications

ASP is not just for prototyping. When using ASP as a solution, design your solution as an
application instead of designing stand-alone ASP pages. As far as objects are concerned, it's best
to take a look at what you need to accomplish and decide what you need, then whether you can
buy the objects or will need to create the objects yourself. Take into consideration caching,
scalability, reusability, security, and consistency.

Bottlenecks

Identify your bottlenecks (that is, the database, network card, or network connection) using the
tools available: WCAT, NetMon, and performance counters. To improve server performance,
take a look at all parts of the system for potential bottlenecks, including hardware configuration
and software settings. This way, if you are ever asked to scale the project larger, you will know
where the work needs to be done.

Browser Connection

In IIS 4.0, use the Response.IsClientConnected property to determine if the browser is still
connected. If the browser is not connected, you can conserve CPU cycles by ceasing the
processing of the ASP page. Refer to the Knowledge Base article Use IsClientConnected to
Check if Browser is Connected.

Buffering

Turn buffering ON. By default it is OFF in IIS 4.0; in IIS 5.0, buffering is ON by default. You
should buffer your ASP files so that you can abort sending a Web page. This might happen if the
script being processed runs into a problem or if a user does not have appropriate security
credentials. If this happens, and if you are using IIS 5.0, you can transfer the user to another page
using Server.Transfer, or clear the buffer (using the Clear method of the Response object) to
send different content to the user.

C++

If you are creating page-level components, you can use server scriptlets, Visual Basic®, Visual
J++™, and Visual C++®. If you are writing components that will be in application or session
state, we recommend that you write them in C++ or Java so you can create them as both-
threaded. Visual Basic is apartment-threaded. See the section below on threading for more
details.

Caching

If your application sends pages to the client via a proxy server, the proxy server may cache pages
to return them more quickly to the client. This reduces the load on the network and the Web
server. To prevent a browser from caching ASP pages, set Response.Expires to some negative
number. This will force the cached pages to expire immediately. If you set Response.Expires to
0, and if your browser clock is behind by a few minutes, the page won't expire immediately. If
your Web site contains objects that do not expire often, such as images, set the expiration to
some time in the future. This will greatly increase the speed at which a page is refreshed or
downloaded. Proxy caching via pragma:nocache is already done for you by IIS, so you don't
have to set this in your headers. More information about caching can be found in Got Any
Cache?

Client-Side Scripts

Distribute the work on your Web site by providing script on both the client and the server. See
Client-Side and Server-Side Objects.

COM Object Debugging

If you create a COM object and use it through ASP with Server.CreateObject, you cannot go
back into your development environment and recompile the COM DLL without restarting the IIS
Admin and W3SVC (Web server) service. Otherwise, the COM DLL will be locked. To restart
these services, do the following:
1. At a command prompt, type net stop iisadmin /y. Please note that this will shut down IIS'
parent service, IIS Admin. This will also shut down FTP and other services that are children of IIS
Admin. If you type only net stop w3svc, inetinfo.exe will not be unloaded.
2. At a command prompt, type net start w3svc. This will restart IIS Admin and the W3SVC service
(Web server).
3. You may recompile at any point after Step 1. Once you refer to an object that loads your DLL,
you must repeat Step 1 before building the component successfully.

Components

Use components to encapsulate the business logic in your ASP applications. You can create your
own components or buy them "off the shelf." Once you have a component, you can reuse it
wherever you need it. Develop your components using C++ or Java. Because Visual Basic is not
marked as both-threaded, you cannot use Visual Basic components within application scope. If
you design your own components, be sure to design components that are stateless (that is, the
methods you define take parameters, rather than having a script set properties then call the
method without the parameters).

Stateless components are far more flexible and reusable. In addition, if you have areas in your
script where you have more than 100 lines of contiguous script, consider turning that script into a
server scriptlet. More information about creating components can be found in the Active Server
Components section of the Server area of the MSDN Library. A comprehensive list of third-
party components available for ASP can be found in the ASP Component Catalog.

Connections

Pool your connections for optimal performance. By pooling your connections, your resources are
allocated more efficiently. For support of multiple logons, provide one connection for read-only
access and one connection for read/write access. In general, avoid putting ADO connections in
session state. ODBC (version 3.0 and later) automatically does connection pooling for you, and
OLE-DB provides session pooling.

Cookie Munger

ASP uses cookies to store the session identifier (ASP SessionID). For machines that have
cookies turned off, the Cookie Munger tool can be used to strip out cookies and put the
information in a URL. This enables the use of "cookies" without actually sending out cookies.
For more information, see Simulating Cookies with the Cookie Munger.

CPU

Design for scalability. Stress your ASP applications at 100% CPU to determine how to best
allocate your resources. Use WCAT or a third-party tool such as Mercury's LoadRunner to tune
your performance.

Data Access Components


Read Improving the Performance of Data Access Components in IIS 4.0 for a detailed
explanation of the techniques that you can use to improve performance.

Database

Use ADO for adding database access to your Web pages via components. ADO can be used to
create small components that connect to any OLE-DB compliant data source, whether it's
relational or non-relational. This includes spreadsheets, databases, or e-mail directories.

Debugging

There are many tools available for debugging, including the Microsoft Script Debugger. The
Script Debugger lets you run your server-side scripts one line at a time, monitor the value of
variables, properties, or array elements during execution, and trace procedures.

Important:   Once you have finished debugging your Web site, don't forget to turn off debugging on
your live servers. This will increase performance.

Dictionary Object

The Dictionary object enables you to look up and store arbitrary key-data pairs rapidly. The
Dictionary object gives you access to items in the array by key, so it is faster to find things that
aren't stored contiguously in memory. Instead, you use a key rather than having to know where
in the array the object is stored.

Disconnected Recordsets

Disconnecting a Recordset means you can view the Recordset's data after severing the
connection to the data store that generated the Recordset. You can create a disconnected ADO
Recordset in-process with a Recordset whose CursorLocation property is adUseClient and
whose ActiveConnection property is set to NULL/Nothing. You can then put the Recordset into
ASP application state and use the Recordset Clone method to share and access the Recordset in
your ASP files. You can then pass this Recordset to a remote client using either RDS or DCOM
(or both together). Read the Knowledge Base articles HOWTO: Getting ADO Disconnected
Recordsets in VBA/C++/Java and INFO: Disconnected Recordsets with ADO or RDS for
detailed information.

Error Handling

You can use the ASPError object to obtain information about an IIS 5.0 error condition that has
occurred in an ASP file. The ASPError object is returned by the Server.GetLastError method.
If the error condition generates an exception and you are using VBScript, use OnErr. In
JScript™, use the try…catch method. Detailed information about error handling can be found in
the article Microsoft JScript Version 5.0 Adds Exception Handling, by Michael Edwards.
Flow Control

Flow control is the ability to set the flow of your ASP application. Flow is controlled through
Response methods and two new Server methods (for IIS 5.0). Using Response.Redirect causes
posted data to be lost. The Response.End method causes ASP to stop when an error is found.
You do not need to call this method after calling Response.Redirect. The Server.Transfer
method is the same as Response.Redirect, except that the work is done on the server and posted
data is not lost. The Server.Execute method will flow into a nested ASP call and return
execution to where you were before the error occurred.

FileSystem Object

The FileSystem object blocks on files. If you are running a high-volume Web site, don't use the
FileSystem object because the performance of accessing a single file will degrade. If you are
using multiple files that are not being accessed at the same time, use of the FileSystem object
will not result in a performance hit.

Global.asa

The Global.asa file is an optional file in which you can specify event procedures and declare
objects that have session or application scope. It is not a content file displayed to the users; it
stores event information and objects used globally by the application. This file must be named
Global.asa and must be stored in the root directory of the application. An application can have
only one Global.asa file. Instead of using the ASP FileSystem object to read files on a page, load
the file(s) into an Application level array in Global.asa.

Glue

Use ASP for the glue and components for the business logic. If you have 100 or more lines of
consecutive script, turn it into a component using server scriptlets (bearing in mind that server
scriptlets have the same limitations as Visual Basic components).

InetLoad

The InetLoad tool can be used to tune your Web site. This tool generates customizable loads on
various Internet services, over a broad range of Internet protocols, including HTTP, SMTP,
POP3, and LDAP. You can use this tool to simulate traffic on your Web site. InetLoad is
available at http://www.thaiware.com/software/internet/IN00470.htm. See also WCATW and
Mercury LoadRunner for tuning tools.

Internationalization

If you are providing a Web site that will be viewed in countries other than the United States, you
can use the CODEPAGE tag within the <% %> delimiters to specify the proper code page.
Alternatively, you can use the Session.CodePage property. Read all about it at
http://www.microsoft.com/workshop/server/nextgen/nextgen .asp. In addition to CODEPAGE,
you can also use the Local Language Identifier (LCID) to determine the language that the user
has set as her preference. Detailed information about LCID can be found in the
IMultiLanguageReference.

Isolation

You can separate IIS, ASP, and components into different processes for better performance. The
drawback to putting these in different processes is the cross-process communication performance
hit. You can put IIS, ASP, and your components in one process. This is the fastest method, but if
your component goes down, it can bring down ASP and IIS. You can put IIS in one process and
ASP with your components in another so that IIS will not crash if your component or ASP
crashes. You can put IIS and ASP in one process and your component in another process. This is
slower than the previous option due to all of the cross-process communication; however, it does
insulate IIS and ASP from a buggy component. The slowest but "safest" option is to put IIS,
ASP, and your components all in separate processes. If one crashes, nothing else will, but the
performance will be very, very slow. It's a better idea to test your components really well.

Component Configuration Protection Speed

IIS, ASP, and components in one process 1 4

IIS in one process, ASP and components in another process 2 3

IIS and ASP in one process, components in another process 3 2

IIS in one process, ASP in one process, components in one process 4 1

Legend: 1 = Least, 4 = Most

Java

Use Java (or C++) to write components. Java is a powerful language that you can use to create
components that are both-threaded.

Logging

You can turn on URI_Query extended logging to log ASP failures. This is not turned on by
default. Turning it on is tricky, so here are the steps:

1. Select a Web or FTP site and open its property sheets.


2. Enable logging if it is disabled and select the W3C Extended log file format.
3. Click Properties.
4. On the Extended Properties property sheet, select the fields you want to log (in this instance,
URI_Query). By default, Time, Client IP Address, Method, URI Stem, and HTTP Status are
enabled.
5. Click Apply.
You can also log to the Windows NT® Server Event Log; however, logging to the Windows NT
Server Event Log is not a good idea if you've got lots of errors or are in debugging mode because
you can fill up the log quickly. Using the Windows NT Performance Monitor, you can log a
variety of error conditions, including how many ASP requests have failed and how many errors
occurred during the script run-time.

Mail

Use Collaboration Data Objects (CDO) to send mail for Windows NT Server. CDO is a
lightweight version of CDO for Exchange. It works on SMTP or Exchange. If you are using
another e-mail protocol, use a third-party component. A comprehensive list is at
http://www.microsoft.com/workshop/server/components/catalog.asp.

<OBJECT> tag

If you need to refer to objects that may not be used, instantiate them by using the <OBJECT> tag
rather than using Server.CreateObject. Using Server.CreateObject causes the object to be
created immediately. If you don't use that object later, you end up wasting resources.

Option Explicit

Turn on the Option Explicit option in your .asp file. Visual Basic enables you to use variables
without explicitly declaring them. Turning on this option helps to identify undefined variables—
you will get an error message for undefined variables. Turning on Option Explicit makes
undeclared variables illegal. Undeclared local variables are as slow as global variables. Turning
on this option will help you find these slugs so that you can get them out of your code.

Order of Execution

ASP does not guarantee the order of execution of script written in different script blocks. It is
strongly recommended that only procedures (functions and subs) be used in script blocks. This
way, you can control the execution order by calling those procedures from the primary script
(that found inside <% and %>) or by calling one procedure from another procedure.

Performance Monitoring

Make sure to monitor the performance of your ASP application. You can use the System Monitor
to determine the number of connections and file transfers for a week-long period on your Web
site. You can also check the Event Viewer to view the Windows NT Event log. (See the logging
topic just above.) Some events that can be helpful include:

 Request.WaitTime (how long the request has been waiting)


 Request.Queued (how many requests are queued up)
 Request.Executing (what's being done concurrently)
 Request.PerSecond (throughput)
 Sessions.Current (to see if there aren't any or how many are going on)
 Request.Disconnected (if the browser has disconnected, stop processing the ASP to reduce the
waste of CPU cycles)
 Templates.Cached (if you are caching too many, you may run out of memory)

Programming Conventions

If you want to have efficient scripts, consult the programming conventions available in the IIS
Resource Kit. These conventions are published online at
http://www.microsoft.com/workshop/server/asp/aspconv.asp .

Queuing

You can use Message Queuing Services to bundle an update or set of updates into a transactional
message that is delivered to a remote server. Message Queuing Services ensures that updates will
be delivered to the remote server, even if the network is currently unavailable. Your application
receives a commit message and can continue with the transaction.

Remote Data Service (RDS)

To tune RDS, increase ADCThreads from its default of six to twelve. The Registry entry for this
parameter is located at
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\ADCT
hreads. The maximum number you can specify is 50. Note that the server must be rebooted for
this change to take effect.

Restarting IIS

By default, sites start automatically when your server restarts. To start, stop, or pause a site in the
Internet Information Services snap-in, select the site you want to start, stop, or pause. Then click
the Start, Stop, or Pause button on the toolbar. If a site stops unexpectedly, the Internet
Information Services snap-in may not correctly indicate the state of the server. Before restarting,
click Stop, and then click Start to restart the site. Use the Cluster Administrator user interface for
starting and stopping clustered sites.

Scalability

Break your include files into multiple small files rather than having one large file, and include
only those files required by your server-side script. If the file that your ASP script includes
contains a large number of functions and variables that are not used by the including script, you
can waste resources and adversely affect performance and scalability.

Scripting Engines

ASP comes with scripting engines for Microsoft Visual Basic® Scripting Edition (VBScript) and
Microsoft JScript. COM Scripting engines for PERL, REXX, and Python are also available
through third-party developers. Cache as many script engines as you have threads running.
Scripting Languages

ASP supports the VBScript, JScript, Perl, and REXX scripting languages.

Security

You can create server-side script using ASP that extracts a user's client certificate and saves the
information. You can then use Secured Sockets Layer (SSL) to catalog and manage the
certificates of users accessing your server. Read more about implementing a secure site with
ASP at http://www.microsoft.com/isn/whitepapers/security.asp.

Self-Tuning

A new feature for IIS 5.0 enables ASP to detect when executing requests are blocked by external
resources, and to automatically provide more threads to simultaneously execute additional
requests and continue normal processing. If the CPU becomes overburdened, ASP cuts down on
the number of threads to reduce thread-switching on simultaneous non-blocking requests.

Server Performance

You can optimize your server performance by techniques like changing Registry settings for
both your system and for IIS. Read this detailed explanation of the settings used on the Microsoft
Web site and how the Web team tunes the site:
http://www.microsoft.com/backstage/whitepaper.htm.

Server Scriptlets

In IIS 5.0, ASP supports server scriptlets. Now you can turn your business logic script
procedures into reusable COM components that you can use in your Web applications, as well as
in other COM-compliant programs.

Service Packs

Be sure to get the latest service pack for IIS and ASP. You can find information about service
packs on the IIS site at http://www.microsoft.com/ntserver/web/default.asp.

Sessions

Use the AspSessionMax metabase property to set the maximum number of concurrent sessions
that IIS will run. Using this property will limit the memory overhead incurred by maintaining
sessions. You can also manage the lifetime of session objects within IIS using the
AspSessionTimeout property.

Session Loss
Session identifiers can be lost for a variety of reasons including bad code, an insufficient
Session.Timeout value, and lack of cookie acceptance. If you are running into this problem,
refer to this very helpful article on ASPAlliance at http://www.aspalliance.com/juan/.

Serialized

Session requests are serialized unless they are in sessionless ASP pages. Sessionless ASP pages
can often improve the responsiveness of your server by eliminating potentially time-consuming
session activity.

SQL Server

By default, the creation of temporary stored procedures is set to ON for SQL Server 2.65 and 3.5
drivers. If you have connection pooling enabled, your temporary stored procedures can be
inadvertently deleted. We recommend that you disable the creation of stored procedures when
running with connection pooling. A detailed explanation of this phenomenon can be found in the
article Improving the Performance of Data Access Components with IIS 4.0,
http://www.microsoft.com/workshop/server/components/daciisperf.asp, in the Connection
Pooling and SQL Server Temporary Stored Procedure section.

Templates

Templates can be either static, like a style sheet or a Word document template, or can include
logic. You can use ASP to provide templates that contain logic that you use for many different
files.

Testing

Test your ASP. Use the tools available with IIS and Visual InterDev 6.0 to test your script and
components.

Threads

Use objects that are marked as "both" for the threading model in your ASP file, if you plan to
store those objects in session or application state. Objects marked "both" or "apartment" will give
you the best performance for objects that are within the scope of the page. ASP does not
guarantee that your session will run on a particular thread. If you use an apartment-threaded
component, that component will always run on the same thread. Components that are both-
threaded can run on any thread. In simple terms: Let's say that you are at a supermarket. You
notice that checkout line number three has only one person in line while the other checkout lines
are long. You choose checkout line number three. If you come back to the store later, you might
see that checkout line number three now has a very long line, so you'd prefer to go to another
checkout that has a shorter line. If you are apartment-threaded, you can't go to another line; you
must go back to the thread that created you. Read
http://www.microsoft.com/workshop/server/components/agility.asp for more information about
threading and ASP components.
Transactions

A transaction is a group of operations that you can have perform as a whole. Transactions are
used with databases to ensure that all related data is updated as a whole. If an error occurs, the
original state of the database is restored.

Tools

Drumbeat, FrontPage 2000, and NetObjects Fusion are tools that you can use to get started using
ASP quickly and easily.

Type Libraries

You can cache type libraries on the server using the AspEnableTypelibCache metabase
property. This property applies to all ASP applications that are running in the same process.

Validation

If you are running a smart browser, it's capable of doing some validation for you. Take
advantage of this whenever you can. Then, perform validation through your scripting. When all
else fails, you can go ahead and access your database on the back end. But remember that
whenever you access the database that lives on the server, you are going to take a performance
hit. This can be very expensive if you have several values in a form that you are validating. If
you know that you will need to run some script on the client side, go ahead and move the code to
the client side for faster performance. When you are running on the client, you have the
processor(s) for your use; the server has to use its processing power for all of the requests it
receives.

Visual InterDev

Use Microsoft Visual InterDev® to quickly create leading-edge Web sites. Visual InterDev
includes a set of integrated database tools that greatly simplify connecting your Web site to
OLE-DB data sources and open database connectivity-compliant (ODBC) databases. For more
information, visit the Microsoft Visual InterDev Web site at
http://msdn.microsoft.com/vinterdev/. For development information, refer to
http://msdn.microsoft.com/vinterdev/technical/articles.asp.

If you are running into problems debugging local ASP in Visual InterDev, the problem might be
with the way you have your permissions set. Open DCCOMCNFG and go to the Catalog Class
and Machine Debug Manager application identifiers. Go to the Security tab and make sure that
your machine Administrators group is listed in the Custom Access and Launch Permissions
dialogs. In addition, be sure to add yourself to the Administrators group.

WCAT
The WCAT tool runs simulated workloads on client/server configurations. Using WCAT, you
can test how IIS and your network configuration respond to a variety of different client requests.
The results of these tests can be used to determine the optimal server and network configuration.
WCAT is designed to evaluate how Internet servers running Windows NT Server and IIS
respond to various workload simulations.

Web Farms

A Web farm is a Web site that is served by more than one computer. As a result, user requests
will not always be routed to the same server. Software is used to distribute the work. This is
known as load balancing. When loads are balanced, it can be difficult to maintain session
information. If you are going to use ASP session management on a Web farm that is load-
balanced, you need to be sure that all requests made within a user session are directed to the
same server. You can do this by writing a Session_OnStart procedure that uses a Response
object to redirect the browser to the Web server where the user's session is running.

XML

Extensible Markup Language (XML) enables you to describe complex data structures to be used
in your Web applications (for C-types, think of a struct). You can use the Microsoft XML Parser
(part of Internet Explorer 4.0) to create ASP applications using XML.

ASP Conventions
 

IIS Resource Kit Team


Microsoft Corporation

Posted March 17, 1998

Contents

Introduction
Using ASP in IIS
ASP Application Directory Structure
Filename Extension Standards
Connection Pooling
Visual Basic Applications as DLLs
Object and Variable Initiation
VBScript Conventions
HTML Conventions for ASP Pages

Introduction
The authors of the IIS Resource Kit have produced this document on ASP authoring conventions
for Web developers. These conventions for developing Active Server Pages (ASP) promote
script efficiency (fast application execution), efficient use of server resources, and consistent
styles. These conventions are adapted from Appendix B, "ASP Standards" of the Internet
Information Server Resource Kit, published by Microsoft Press, 1998. The Resource Kit
provides a wealth of information on ASP application development.

The ASP standards document (in HTML and Word format) is offered to assist with the adoption
of ASP in your organization. If you have requirements to create standards before deploying new
technologies, you can edit this document to fit your specific standards styles and adapt it to fit
your in-house standards documentation.

Please send comments and suggestions for improving the next version of the Resource Kit to
rkinput@microsoft.com.

Using ASP in IIS


To make the most efficient use of your server resources, you should use the .asp filename
extension only for pages that contain scripts.

Writing Scripts for Browsers

When possible, write scripts to be executed by the browser, rather than the server. By using the
client platform to perform tasks such as data validation, edit-checking, and selecting simple
conditional output, you can reserve server resources for those tasks requiring ASP.

ASP Application Directory Structure


The directory and file conventions suggested in this section optimize ASP application directory
structure for consistency, clarity, and ease of use.

The directories and files described are listed here:

/Application_Root

Default.htm

Global.asa

/Classes

/Content

/Media
/Themes

/Data

/DLLs

/Helpers (not in the Web site directories identifiable to users)

Application Root Directory

For readability and clarity, the application root directory should be named in a way that conveys
what the site is about. For example, a site about financial research might be named
/FinancialResearch or /FR. Avoid application root names that might be misidentified as standard
subdirectories of a site, such as /Media or /Content. Also, avoid names that sound like part
numbers or codes, such as /FR98346A.

While the site is being developed, the application root directory should be stored under
/InetPub/Wwwroot.

The root directory of every application should contain at least these files:

 Default.htm
 Global.asa

Default.htm or Default.asp should be the default home page for the site, and the server default
should be set accordingly. This combination enables users to find sites in your organization
consistently, by typing the server address plus the application root directory name.

Global.asa contains scripts that affect the Application object and Session object. For example,
Global.asa scripts make application- and session-scope variables available at startup. Global.asa
should be present at the application root level for every ASP application.

/Classes Directory

The /Classes directory holds Java classes used by the application.

/Content Directory

The /Content directory holds all .htm files and all .asp files that may be run by a user of the site.
The /Content directory has execute permissions. Keeping all scripted pages in this directory
branch simplifies permissions management.

/Media Sub-directory

A sub-directory of the /Content directory, Media should contain sub-directories for sounds,
images, animation files, .avi files, and similar items. An /Images sub-directory should contain
bullets, buttons, icons, and others that are used throughout the application independently of
changing themes.

/Themes Sub-directory

The /Themes directory is a sub-directory of the /Content directory. Establish a convention of


using the /Themes directory to enable application-wide changes to the look of a site. The
directory should contain style sheets, bullets, buttons, icons, rules, and similar items organized so
that you can change the look of an application by changing any or all the theme-related items
easily. Each item in the /Theme directory can be linked dynamically by setting an application
variable to the image's virtual path. Themes are stored in Options.txt and assigned to the
Application object in Global.asa.

/Data Directory

This directory should contain all database access information such as SQL scripts, file-based
dataset names or other data needed by the application.

/DLLs Directory

This directory should contain COM server components and Visual Basic 5.0 run-time DLLs,
such as Vbrun500.dll and Msvbvm50.dll.

Helper Files

Helper files are include files or text files that make information available across the application.
For security reasons the directory containing helper files should not be stored in the published
Web space (the Web site directories identifiable to users).

Filename Extension Standards


This section suggests conventions for standardizing on filename extensions, accounting for the
types of files containing scripts, or HTML and scripts (VBScript or JScript) together.

Extensions for Page Files

Standards:

 .asp—for pages containing ASP scripts


 .htm—for straight HTML pages

You must use the .asp extension for pages that contain ASP scripts. To save time and resources
when serving pages, use the .htm extension for files that don't require server-side script
execution.
Extensions for Included Files

Standards:

 .inc—for large amounts of data, with scripting, to be included in a page


 .txt—for text-formatted data files, without scripting, to be included in a page

For consistency, use include files to make specific information available to more than one
referring page (changes to include files are distributed to all the pages that include them).

Connection Pooling
One of the potential bottlenecks in ASP application performance is connection management. If
not managed properly, the opening and closing of connections can happen too frequently and can
cause reduced server performance. Windows NT Server 4.0 features built-in support for
Connection Pooling, maintaining connections optimally to achieve faster application
performance and graceful timeout management with less coding effort.

To use ODBC connection pooling:

 Configure the driver for the database to which you are establishing a connection.
 Check the Windows NT registry to verify that Connection Pooling is on, and let it handle
the connection logic.
 If Connection Pooling is off, use Regedit32 to turn it on in the Windows NT registry.
 Open individual connections—in your ADO code—just before you need data access on
each individual page.
 Close your connections when the data access activities are complete.

Enabling connection pooling involves setting the CPTimeout property. For descriptions and
examples on how to configure the CPTimeout property in the registry, see Internet Information
Server Resource Kit, Chapter 6, "Data Access and Transactions."

Enabling connection pooling involves setting the CPTimeout property. For descriptions and
examples on how to configure the CPTimeout property in the registry, see Internet Information
Server Resource Kit, Chapter 6, "Data Access and Transactions."

Visual Basic Applications as DLLs


When you convert Visual Basic applications for use in ASP, they should be run as DLLs
(components), rather than being converted to VBScript. Visual Basic DLLs will generally run
more efficiently than scripts written in any scripting language. Encapsulate the Visual Basic code
in DLLs and use Server.CreateObject().

Visual Basic 5.0 should be used to create an ActiveX DLL that has its project properties set to
Run in Unattended Mode, Apartment Model Threaded, and Multi-instance.
Object and Variable Initiation
The following discussion focuses on initializing and setting dimensions for objects and variables
to achieve speed of execution and efficient use of server resources.

Application-Wide Scope for Convenience

Information stored in variables with application-wide scope is in memory and is cached for
access by any page in the application. Establish a convention to give application scope to
variables used often within an application if the values do not change frequently.

Whatever the potential benefits, use caution in deciding whether or not to give application scope
to an object. It can potentially affect performance and decrease reliability (your application could
hang). For best results, use application scope for objects with threading marked BOTH,
aggregating the FreeThreadedMarshaler.

Declaring Objects with the <OBJECT> Tag

For objects that may or may not be used in an application, it's often most efficient to declare the
objects without instantiating them until the need to use them arises (until they are referenced). To
declare an object without actually creating it, use the <OBJECT> tag on the page instead of
Server.CreateObject().

Another advantage to bear in mind is that the <OBJECT> tag uses CLASSIDs, which are unique
and tend to eliminate name collisions. The PROGIDs used by Server.Create.Object() do not
force unique names, creating the possibility of name collisions.

Also, the <OBJECT> tag is supported in Global.asa and can be used to define scope using
SCOPE or SESSION as values.

VBScript Conventions
The following suggested conventions apply to the development of ASP scripts written in
Microsoft Visual Basic Scripting Edition (VBScript) and are designed to enhance consistency,
performance, and reliability.

Comments in Scripts

Write consistent comment blocks near the top of each page listing, such as the filename, the
group developing the file (not the person--e-mail should go to a group alias), the date developed,
the HTML standard, and clear descriptions of all changes made.

Scripts that are commented out should be deleted unless they are placeholders, in which case
they should be labeled as such.
Use comments to explain obscure or complex code. Do not leave a phrase such as the following
without a comment:

Copy
If Err = -214983642 Then

Use comments to explain empty statements used as placeholders, such as:

Copy
If...Then...Else...Endif

Constant Names

To clearly distinguish constants from other elements, use all uppercase when naming them. An
underscore can be used to separate terms when necessary. Example:

Copy
Const MIN_QUAL = 25

Minimize Context Switching

For readability, try to minimize context-switching between HTML and scripts. When possible,
use a few large blocks of script on a page instead of several scattered fragments.

Dictionary Object: Speed Access to Information

The VBScript Dictionary object enables fast lookup of arbitrary key/data pairs. Because the
Dictionary object gives you access to array items by key, it is faster for finding items that are
not in contiguous memory since you are specifying a key, rather than knowing where in the array
the item is located.

Use the Dictionary object when you have set a high priority on fast searches of nonlinear data.

Delimiting Lines of Script for Readability

Lines of script should be blocked between a pair of delimiters, rather than written with delimiters
on each line.

Instead of this:

Copy
<% strEmail = Session("Email") %>
<% strFirstName = Request.Form ("FirstName") %>
<% strLastName = Request.Form ("LastName") %>
Do this:

Copy
<%
strEmail = Session("Email")
strFirstName = Request.Form ("FirstName")
strLastName = Request.Form ("LastName")
%>

For a single stand-alone line of script, keep the delimiters on the same line as the script.
Example:

Copy
<% strEmail = Session("Email") %>

If the line of script consists of an equal sign and a variable, make the equal sign part of the
delimiter. Example:

Copy
<%= strSubscrLName %>

Similarly, if the line of script specifies an ASP declarative, include the @ sign as part of the
opening delimiter. Example:

Copy
<%@ LANGUAGE = VBScript %>

Enable Session State Directive

Using the Enable Session State directive (set in Internet Services Manager) for your site enables
the detailed tracking of user requests.

Save the resources used by IIS to process scripts for pages not using session state information by
setting the Enable Session State directive to FALSE for those pages:

Copy
<%@ ENABLESESSIONSTATE = False %>

Language Default

Override the scripting language being used as the server's default language (VBScript) by using
the @ language directive. For example, to ensure that the default language is JScript, put the
following code at the top of each ASP page:
Copy
<%@ LANGUAGE = JScript %>

Layout Order of Scripts in ASP Pages

The following list summarizes the layout of VBScript scripts in an .asp file, in orderfromtop to
bottom.

 Specify language.
 Use Option Explicit statement.
 List function library includes.
 Declare page-scoped variables.
 Assign values to page-scoped variables.
 Code HTML and in-line scripting.
 List functions called by in-line scripts.

The first two script statements should specify declaratives and Option Explicit to force explicit
variable declaration.

Inline scripts with HTML markup should call objects of functions placed at the bottom of the
page. The inline scripts should be short and readable, even if this requires splitting out
procedures to be placed at the bottom of the page.

Blank Lines in Files

In general, use blank lines sparingly. You should remove all blank lines at the beginnings and
ends of files, but may want to include one blank line between statements, to increase readability.

Object and Procedure Call Names

To clearly distinguish object names and procedure calls from elements such as variables, begin
each object name or procedure call with a verb. Use initial capitalization for each term within an
object name or procedure call. The following list suggests some naming conventions that could
be used to name objects for some typical activities.

Name Function Example


AddNew add new records Customer.AddNew
Update edit records Customer.Update
Remove delete records Customer.Remove
Get return row from database Customer.GetNewest
List return multiple rows Customer.GetNew

To limit criteria for methods that return information, use From and For with a method or
function name.
Name Function Example
GetFor returns criteria-based row Customer.GetForName
ListFor returns criteria-based multiple rows Customer.ListForPeriod

Object Naming

As with variables and statements, used mixed case in naming objects, and in spelling out names
of intrinsic objects. Capitalize the first letter of each term.

Use descriptive names for objects, even though this requires more characters per name.

The following example conforms to this convention (cnn prefixes an ADO connection variable,
see "Variable Names" below):

Copy
Set cnnSQL = Server.CreateObject("ADODB.Connection")
Set cnnSQLServer = Server.CreateObject("ADODB.Connection")

These do not conform:

Copy
Set cnnS = Server.CreateObject("ADODB.Connection")
Set cnnsql = Server.CreateObject("ADODB.Connection")

Paths, using MapPath

Consider using MapPath instead of literal paths in ASP applications. The ASP
Server.MapPath method allows you to physically relocate an ASP application without recoding
scripts. This saves program modification and maintenance effort.

Performance is affected slightly, because every time you use MapPath in a script, IIS must
retrieve the current server path. Consider placing the result of the method call in an application
variable to avoid retrieving the server path.

Select Case Statement for Readability

For readability and efficiency, use the Select Case statement in place of If...Else to repeatedly
check for the same variable for different values. For example:

Copy
Select Case intYrsService
Case 0 to 5
strMessage = "You have ten days paid leave this year."
Case 6 to 15
strMessage = "You have fifteen days paid leave this year."
Case 15 to 30
strMessage = "You have twenty days paid leave this year."
Case 30 to 100
strMessage = "Will you never leave?"
End Select

Spaces in Scripts

To enhance script readability, use spaces consistently:

 Before and after operators, such as plus and equal.


 After commas, as when passing parameters.
 Exception: do not use spaces between arguments in ADO connection strings.

Statement Styles

Each scripting language has its own conventions for capitalization, indentation, and other style-
related characteristics. Since VBScript is case-insensitive, capitalization conventions can be
created to improve readability, as the following suggestions illustrate.

If...Then...Else...End If statements:

 Capitalize the first letter of If, Then, Else, and End If.
 Indent the clauses two spaces, or one tab.
 Put spaces at each end of an equal sign.
 Avoid using unnecessary parentheses.

Correct example:

Copy
<%
If Request("FName") = "" Then
Response.Clear
Response.Redirect "test.html"
Else
Response.Write Request("FName")
End If
%>

Similarly, capitalize the first letters of function and subroutine statements, and indent their
definitions 2 spaces. Example:

Copy
Sub SessionOnStart
Set Session("MyId") = Request.ServerVariables(...)
End Sub
As with variable names, use mixed case, capitalizing the first letter in each term in a name.
Avoid underscores. Example:

Copy
FirstName

String Concatenation

For the sake of consistency and to achieve more self-documenting scripts, use the string
concatenator (&), instead of a plus (+) sign.

String Function

Use the String() function to create a string consisting of repeated characters. Example: a string
of non-breaking spaces (&nbsp;). The String() function is more readable and elegant than, for
example:

Copy
For I = 0 to 11 . . .

Case Values

Keep case consistent in both variable assignment and logical tests by using UCase() or LCase().
This is especially important when assigning and logically testing HTML intrinsic form controls,
such as check boxes and radio buttons.

Trimming Values

Be consistent in trimming values. For example, consider always trimming values before putting
them in state. This will eliminate errors in processing caused by inconsistencies in trimming
schemes.

Variable Declaration

Declaring variables explicitly helps expose errors, such as misspelled variable names. To make
code more reliable and readable use the Option Explicit statement in VBScript.

When you want to use strong variable typing, the logic should be programmed into a component
built with a language that supports it, such as Visual Basic 5.0 or Visual J++. Loosely typed
variables, such as Variants in VBScript, can affect performance, especially when mathematical
computations are involved.

Variable Names for Consistency


For consistency in naming variables, use initial capital letters in variable names (do not capitalize
prefixes).

To make the intended use of a variable clear to others reading your script, use three-character
prefixes to indicate data type. Even though explicit typing is not supported in VBScript, the use
of prefixes is recommended to denote the intended data type.

Table B.1 Suggested Prefixes for Indicating the Data Type of a Variable

Data Type Prefix


Boolean bln
Byte byt
Collection object
col
Currency cur
Date-time dtm
Double dbl
Error err
Integer int
Long lng
Object obj
Single sng
String str
User-defined type
udt
Variant vnt
ADO command cmd
Jul 17, 1998 editor's note: This was previously published as cmn in the
Resouce Kit; we now recommend cmd.
ADO connection cnn
ADO field fld
ADO parameter prm
ADO recordset rst

To keep variable name lengths reasonable, use standardized abbreviations. For clarity, keep
abbreviations consistent throughout an application, or group of related applications.

Instead of:

Copy
strSocialSecurityNumber

Use:

Copy
StrSSN
Variable Scope for Performance

Use local scope (within subroutines and functions) for variables unless you have a compelling
reason to use global scope. Local variables are resolved into table lookups when compiled,
enabling fast execution at run time.

Declare global variables using the Dim statement before using them. This saves valuable first-
use time by eliminating a search of the entire variable list.

HTML Conventions for ASP Pages


ASP applications serve dynamic information in standard HTML format. This means that you can
customize information for a wide range of users.

Support Text-Only Browsing

Many users browse the Web in text-only mode in order to speed up the display of information to
their browsers. To ensure that you present as much content as possible to these users, take the
following steps to support text-only display:

 Include text-only navigation objects, such as menus.


 Include the alternative (ALT) parameter with each image tag to provide information
about images.

<IMG SRC="gravity.jpg" ALT="Picture of apple falling">

 When providing client-side imagemaps, add a text-only list of the mapped areas, with
links to the information that would have been loaded if the user had clicked on a map
link.

Checking HTML Files

You should check and debug your HTML code formally, using either a dedicated HTML
checker or an HTML editor that includes a checker.

 Choose an HTML checker that helps enforce your HTML version standard.
 Debug each new HTML file as it is developed. Then debug your files again after each
time they are modified.

To debug an HTML page that contains ASP scripts:

 Run the page that contains ASP scripts.


 View the source.
 Save the output, which is pure HTML.
 Run the saved output through an HTML checker.

This process is especially important for ASP pages that include forms. In these cases, HTML
errors may corrupt the Request object sent from the browser to the server and cause a run-time
error.

Using the 216-Color Palette

Color palette mismatches are ever-present concerns when you are creating images for a multi-
platform Web. Even images in formats that require compact palettes, such as GIF (256 colors
max), often display disparate colors when displayed on different platforms, such as Mac OS,
Windows 95, and UNIX.

To ensure that your images display the same colors in different browsers on diverse platforms,
use the 216-color palette—also called the safety palette, or the 6x6x6 palette. This allows nearly
as many colors as a GIF image can display, and displays consistent colors across systems.

Designing for Small Screens

Small-screen formats are still the standard for many users. Although larger formats are making
progress, even 800 by 600 is too large to fit on millions of displays. For example, there are about
ten million Macintoshes currently in use, many of which display 640 by 480 pixels.

To accommodate a broad spectrum of users, including those with small screens, design for 640
by 480 pixels.

For usability with small screens, keep the average line of text to approximately 12 words.

Displaying Standard Error Messages

For consistency and to make error messages informative, use standard Response.Status values,
such as "401 Unauthorized - Logon failed" and other IIS standard responses in your pages. You
can customize error messages in cases where additional information is needed.

Using Object Statements with Embed Statements

To use interactive objects delivered to multiple browsers you must code for browsers that do not
support the HTML <OBJECT> tag.

To script the use of interactive objects, ActiveX Controls, or Java applets in HTML pages
designed for a wide range of browsers:

 Use the <OBJECT> tag to place the object on the page.


 Add the <EMBED> tag to support browsers that do not support the <OBJECT> tag.
 Add a display object using the <NOEMBED> tag for browsers that cannot "play" the
object.

The following example places a Shockwave control onto a page, and provides for the
contingencies in the preceding sections:

Copy
<OBJECT ID="ShockedPMDauntless">
CLASSID="clsid:59CCB4A0-727D-11CF-AC36-00AA00A47DD2"
CODEBASE="http://www.fabrikam.com/marketing/movers/..."
WIDTH=180 HEIGHT=120
>
<PARAM NAME="swURL" VALUE="dauntless.dcr">
<EMBED SRC="dauntless.dcr" ALT="Movie of Fabrikam

Dauntless model in
action" WIDTH=180 HEIGHT=120>
</EMBED>
<NOEMBED>
<IMG SRC="dauntless.gif" ALT="Picture of Fabrikam

Dauntless model in
action" WIDTH=180 HEIGHT=120>
</NOEMBED>
</OBJECT>

Building a Web-based Event Calendar


 

Scott Semyan
Microsoft Corporation

July 2000

Summary: This article describes how to build a calendar using ASP, Internet Information
Services, and Microsoft SQL Server. (18 printed pages)

Contents

Introduction
SQL Back End
ASP Front End
Performance Issues
Conclusion

Introduction
In this article I will demonstrate how to build a Web-based calendar. This article provides a good
introduction to data-driven Web sites for developers new to Active Server Pages (ASP),
Structured Query Language (SQL), and ActiveX® Data Objects (ADO). For more experienced
developers, I also provide tips on scalability.

Figure 1. A Web-based event calendar

What Are Web-based Calendars?

Web-based calendars have become quite popular recently. Originally people kept their schedules
in personal information managers, such as Microsoft® Outlook®. The problem with these
calendars is that, to put it simply, they are personal and it is difficult to share the calendar out for
others to see or use. What was needed was a way to either make your personal calendar available
for others to see, or to have a group calendar that many people could use at the same time. With
the rise of the Internet—available anytime, anywhere—Web-based calendars became feasible.

What Can You Do with Web-based Calendars?

A Web-based calendar allows you to share your schedule with others or manage a calendar for a
team of people. Sharing your calendar is useful if you want people to have access to your
schedule. Team calendars, on the other hand, are useful for showing major events, such as
deadlines or milestones, and also for showing when people will be on vacation.

What Is Presented Here?

At my company we have an intranet site where we consolidate all the information relevant to our
team, including scheduled vacations, milestones, and holidays. To do this I built a simple Web-
based calendar that allowed anyone to view, add, and/or remove events (see Figure 1).

In this article I describe how to build a very simple Web-based calendar using ASP pages within
Microsoft Internet Information Services (IIS) and Microsoft SQL Server™. At the conclusion of
this article I will discuss the performance implications that must be considered when scaling this
application up to many users. For people new to IIS and ASP, this article can be considered a
good tutorial for building data-driven Web sites.

SQL Back End


What Data to Save?

The first question is what kind of data do you want to save for each date? For my calendar, I
simply needed to save a string of text, up to 100 characters long, that identified the nature of the
event. One could easily extend this data model to include much more then just a text string.

Schema
Calendar.sql

The SQL code is contained in the following code snippet:

Copy
--------------------------------------------------
-- Tables
--------------------------------------------------

create table Schedule


(
idSchedule smallint identity primary key,
dtDate smalldatetime not null,
vcEvent varchar(100) not null
)
go

--------------------------------------------------
-- Stored Procedures
--------------------------------------------------

create procedure GetSchedule (@nMonth tinyint, @nYear smallint)


as
select idSchedule, convert(varchar, datepart(dd, dtDate)) 'nDay', vcEvent
from Schedule
where datepart(yy, dtDate) = @nYear and datepart(mm, dtDate) = @nMonth
order by datepart(dd, dtDate)
go

create procedure AddEvent (@vcDate varchar(20), @vcEvent varchar(100))


as
insert Schedule
select @vcDate, @vcEvent
go

create procedure DeleteEvent (@idSchedule smallint)


as
delete Schedule where idSchedule = @idSchedule
go

For my schedule table, I use an identity key (self incrementing) as the primary key so I don't
have to make a unique key myself. I choose a smallint for idSchedule because, for my needs, I
didn't expect to ever have more than 32,000 different events. For a larger-scale application, you
would probably want to use a long integer to give you up to 2 billion records. I save the date as a
smalldatetime to save space because I don't need to record time down to the second. A normal
datetime, which saves times accurately down to milliseconds, uses twice the space of a
smalldatetime, which is accurate down to a minute. Larger-scale applications might want to
examine other ways to record dates that take up even less space (for example, an integer showing
the number of days after a certain day, such as Jan 1, 1970).

For my data I choose a variable length character string (varchar) up to 100 characters long. In
SQL Server 7.0 you could use a nvarchar, which would hold Unicode characters, making your
application worldwide capable. There are, however, issues with creating Web pages for an
international audience that are beyond the scope of this discussion.

Stored Procedures

A quick note on stored procedures in SQL: Stored procedures are better than hard-coded SQL in
the ASP code for two primary reasons. First, keeping the data access code separate from the
presentation code ensures the independence of the data. This allows you to change the data
structure (and its accompanying stored procedures) without having to alter the ASP pages. This
is classic Microsoft Windows® DNA n-tier architecture. The second reason why stored
procedures are preferred is that they will run faster than a text query because they are parsed the
first time they are called. Therefore, subsequent calls do not have to parse the procedure again.

I need three stored procedures to access and manipulate the data in this table: GetSchedule,
AddEvent and DeleteEvent.

For the GetSchedule procedure I pass in the month and year of the data I want back. Next, I use
the Datepart() function to get the numerical day of the event. I will then use this number to
match up with the day of the month as I am building the calendar. It is important to order the
results by day, as we will see later.

The AddEvent procedure simply adds a text event to a given date. I do not worry about adding
duplicate events because all the events are marked with a unique schedule ID.

The unique schedule ID is all that is needed to remove an event from the schedule. Passing this
into the DeleteEvent procedure removes the event.

ASP Front End


Basic UI

Figure 1 shows the main user interface (UI). The UI is set up like a wall calendar. My week
starts on Sunday and includes 7 days. For the sake of simplicity, I have refrained from doing
heavy formatting, but it would be easy to use style sheets to make this calendar look much more
professional. From this main page, the user can see what events have been scheduled. In
addition, they can move forward and backward in the calendar by month using the links at the
bottom, or they can select a specific month and year using the drop-down list boxes in the upper-
left corner of the page. The link to the Add/Remove Events page is directly below the calendar.

ASP Code Basics

Header.asp

Copy
<%@ LANGUAGE="VBSCRIPT"
ENABLESESSIONSTATE = False %>
<%
'********************************************************************
' Name: Header.asp
'
' Purpose: Header include file used to start all pages
' also includes global functions
'
'********************************************************************

Option Explicit
Response.Buffer = True
Response.Expires = 0

sub DoHeader(strTitle)
%>
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso8859-1">
<title>Event Calendar - <%= strTitle %></title>
</head>

<body bgcolor="white" link="blue" alink="blue" vlink="blue">


<basefont face="Verdana, Arial">

<center><h1>Event Calendar</h1>
<h3><%= strTitle %></h3>
<%
end sub

sub DoFooter(strTitle)
%>
</center>
</body></html>
<%
end sub

function GetDataConnection()
dim oConn, strConn
Set oConn = Server.CreateObject("ADODB.Connection")
strConn = "Provider=SQLOLEDB; Data Source=adspm; Initial Catalog=TeamWeb; "
strConn = strConn & "User Id=TeamWeb; Password=x"
oConn.Open strConn
set GetDataConnection = oConn
end function
%>

When I code a Web site in ASP I like to have a single header page for the entire site. This allows
me to have one page on which to put commonly used functions, styles, Microsoft JScript®, etc.
For this site, I have set up a header page (see the preceding code example) that sets some ASP
settings for the entire site and contains three functions that I use in all other pages of the site: an
HTML header and footer, and my data connection code.

The first thing I do is set the language to Microsoft Visual Basic® Scripting Edition (VBScript)
and disable session state. Setting the language is not necessary but is a good idea. Also, this site
makes no use of ASP session state, which I explicitly tell IIS, thus improving performance
slightly. My other coding conventions are to set Option Explicit (meaning I must dim variables
before using them), buffered output (IIS will hold output and then spit it all out at once-this
improves performance), and to set the page to expire immediately (so that users will always get
fresh pages).

I use a DoHeader function that handles all of my HTML header code. I pass in the name of the
page, which is displayed both in the HTML title and the H3 tag at the top of the page. This gives
me a single place to edit HTML BODY attributes, styles, etc. Similar to the DoHeader function,
I like to have a footer function in case I need to add a common footer (with contact information,
etc.).

ADO lets me connect my ASP page with my SQL database very easily. First I create a
connection to the database. To get a recordset I call the Execute method of the Connection
object passing in a text string of the command I wish to perform. Once I have the recordset, I can
loop through it. Header.asp contains the function to get my data connections. This means I only
have one place where I need to edit connection information (server, user, password) if my data
source changes. Note that at the end of the function I must use the set command to pass the new
connection out as a result.

How It Works

Calendar.asp

Copy
<!--#includes file="Header.asp"-->
<%
'********************************************************************
' Name: Calendar.asp
'
' Purpose: Main calendar page that shows events in a calendar format
'
'********************************************************************

dim dbConn, rs, nDex, nMonth, nYear, dtDate

' Get the current date


dtDate = Now()

' Set the Month and Year


nMonth = Request.QueryString("nMonth")
nYear = Request.QueryString("nYear")
if nMonth = "" then nMonth = Month(dtDate)
if nYear = "" then nYear = Year(dtDate)

' Set the date to the first of the current month


dtDate = DateSerial(nYear, nMonth, 1)

Set dbConn = GetDataConnection


Set rs = dbConn.Execute ("GetSchedule " & nMonth & ", " & nYear)
DoHeader(MonthName(Month(dtDate)) & "&nbsp;&nbsp;" & nYear)
%>
<form method="get" name="DateSelect" action="Calendar.asp">

<table width=700>
<tr><td colspan=2><select name="nMonth" onChange="DateSelect.submit();"><%
for nDex = 1 to 12
Response.Write "<option value=""" & nDex & """"
if MonthName(nDex) = MonthName(nMonth) then
Response.Write " selected"
end if
Response.Write ">" & MonthName(nDex)
next %></select>&nbsp;
<select name="nYear" onChange="DateSelect.submit();"><%
' Note: I have set the year to be between 1999 and 2000
for nDex = 1999 to 2002
Response.Write "<option value=""" & nDex & """"
if nDex = CInt(nYear) then Response.Write " selected"
Response.Write ">" & nDex
next %></select></td></tr>

<tr><td colspan=2>
<table border=1 bgcolor="gray" cellpadding=3>
<tr bgcolor="Blue"><td width=90><font
color="white"><b>Sunday</b></font></td>
<td width=90><font color="white"><b>Monday</b></font></td>
<td width=90><font color="white"><b>Tuesday</b></font></td>
<td width=90><font color="white"><b>Wednesday</b></font></td>
<td width=90><font color="white"><b>Thursday</b></font></td>
<td width=90><font color="white"><b>Friday</b></font></td>
<td width=90><font color="white"><b>Saturday</b></font></td></tr>
<tr bgcolor="#ffffc0">
<%
' Add blank cells until the proper day
for nDex = 1 to Weekday(dtDate) - 1
Response.Write "<td bgcolor=""#c0c0c0"">&nbsp;</td>"
next

do
Response.Write "<td valign=""top"">" & Day(dtDate) & "<br>&nbsp;<br>"

if not rs.EOF then


do
if CInt(rs("nDay")) <> CInt(Day(dtDate)) then exit do

Response.Write "<font size=""-1""><b>" & rs("vcEvent")


Response.Write "</b></font><br>"
rs.MoveNext

if rs.EOF then exit do


loop
end if

Response.Write "</td>"

if WeekDay(dtDate) = 7 then
Response.Write "</tr>" & vbCrLf & "<tr bgcolor=""#ffffc0"">"
end if
dtDate = DateAdd("d", 1, dtDate)
loop until (Month(dtDate) <> CInt(nMonth))

' Add blank cells to fill out the rest of the month if needed
if Weekday(dtDate) <> 1 then
for nDex = Weekday(dtDate) to 7
Response.Write "<td bgcolor=""#C0C0C0"">&nbsp;</td>"
next
end if
%>
</tr>
</table></td></tr>

<tr><td colspan=2 align="center"><b><a


href="Events.asp?nMonth=<%= nMonth %>&nYear=<%= nYear %>"
>Add/Remove Events</a></td></tr>

<tr><td><a href="Calendar.asp?nMonth=<%
if nMonth = 1 then
Response.Write "12&nYear=" & nYear - 1
else
Response.Write nMonth - 1 & "&nYear=" & nYear
end if %>"><b>&lt;- Previous Month</b></a></td>
<td align=right><a href="Calendar.asp?nMonth=<%
if nMonth = 12 then
Response.Write "1&nYear=" & nYear + 1
else
Response.Write nMonth + 1 & "&nYear=" & nYear
end if %>"><b>Next Month - &gt;</b></a>
</td>
</tr>
</table>

</form>

<%
DoFooter("Home")
%>

The most challenging part of this project was building an HTML calendar that was accurate.
There are many algorithms to determine-for example, how many days are in each month,
whether a year is a leap year, etc. Rather than work through all that, I used the date object within
Visual Basic to build my calendar.

To lay out the calendar for a given month, I first create a date object for the first day of that
month and year. I then simply increment the date forward a day at a time using the DateAdd()
function. I can then use the built-in methods to show what day of the week it is, and when the
month ends. I also know the day of the month and use this to synchronize with my schedule
information. This allows me to build a table that shows a calendar.

The Event Calendar page is built dynamically using the date and year passed in the query string.
If no month or year is passed in, the current month and year are used.
This makes it easy to build UI that can move between months. The link to go back a month is
created by calling Calendar.asp and supplying a query string that indicates the previous month
(and decrementing the year if we are in January). Moving forward a month is just as easy (first
checking to see if we are in December). Moving to a specific month and year is easier still. All
we do is set up a form with Calendar.asp as the target, fill some drop-down list boxes with the
months and years we want to cover, and then attach a submit event to the onChange() event for
the drop-downs lists. This allows the page to update automatically when the user picks a new
month or year. Notice how I use the MonthName() function to list the months.

Showing events is quite easy. First I pull out the events for the given month using ADO to
connect to my SQL database. I call my GetSchedule stored procedure and pass in the month and
year in question. This gives me a recordset containing the list of events, along with the day in
which they occur (sorted by day).

Now, while I am building the calendar, I simply show the events on the day in which they occur.
I can do this because I know my events are sorted by day.

Figure 2. The Add/Remove Events page

The Add/Remove Events page allows a user to either add a new event or remove an existing
event. The page is accessed by first moving the calendar to the proper month and then clicking
the Add/Remove Event link. This link is built to include a query string that indicates what month
and year to add/remove events.

The list of current events for the month is generated using the same GetSchedule stored
procedure as Calendar.asp. This time all we need to do is simply cycle through the recordset to
show all the events for the month.

Events.asp

Copy
<!--#includes file="Header.asp"-->
<%
'********************************************************************
' Name: Events.asp
'
' Purpose: Used to add and remove events from the event database.
'
'********************************************************************

dim dbConn, rs, nDex, nMonth, nYear, dtDate, dtTemp

' Get the current date


dtDate = Now()

' Set the Month and Year


nMonth = Request("nMonth")
nYear = Request("nYear")
if nMonth = "" then nMonth = Month(dtDate)
if nYear = "" then nYear = Year(dtDate)
Set dbConn = GetDataConnection
Set rs = dbConn.Execute ("GetSchedule " & nMonth & ", " & nYear)

DoHeader("Add/Remove Events")
%>

<form method="get" action="AddEvent.asp">

<br>Currently Scheduled Events for <b><%


Response.Write MonthName(nMonth) & "&nbsp;&nbsp;" & nYear
%></b>:<p>
<table bgcolor="gray" border=1 cellpadding=3>
<tr bgcolor="Blue"><td><font color="white"><b>Day</b></font></td>
<td colspan=2><font color="white"><b>Event</b></font></td></tr>

<% if rs.EOF then


Response.Write "<tr><td colspan=3 bgcolor=""#ffffc0"">No events
listed</td></tr>"
end if

while not rs.EOF


Response.Write "<tr bgcolor=""#ffffc0""><td>" & rs("nDay") & "</td><td>"
Response.Write rs("vcEvent") & "</td><td><input type=""button""
value=""Remove"""
Response.Write " onClick=""window.location.href='RemoveEvent.asp?
nMonth=" & nMonth
Response.Write "&nYear=" & nYear & "&idSchedule=" & rs("idSchedule") &
"'""></td></tr>"
rs.MoveNext
wend
%></table>

<p><br>
<table bgcolor="gray" border=1 cellpadding=3>
<tr bgcolor="Blue"><td><font color="white"><b>Add New
Event:</b></font></td></tr>
<tr bgcolor="#ffffc0"><td>Event:
<input type="text" size=30 maxlength=100 name="Event"> Day: <select
name="nDay"><%
' Set the date to the first of the current month
dtDate = DateSerial(nYear, nMonth, 1)

dtTemp = dtDate
do
Response.Write "<option value=""" & Day(dtTemp) & """>" &
Day(dtTemp)
dtTemp = DateAdd("d", 1, dtTemp)
loop until (Month(dtTemp) <> CInt(nMonth)) %></select>
<input type="hidden" name="nMonth" value="<%= nMonth %>">
<input type="hidden" name="nYear" value="<%= nYear %>">
<input type="Submit" value="Add Event"></td></tr>
</table>
</form>

<p><a href="Calendar.asp?nMonth=<%= nMonth %>&nYear=<%= nYear %>">Back to


Calendar</a>
<%
DoFooter("Home")
%>

To add a new event the user simply types their event into the form and then clicks the Submit
button. The form element is limited to 100 characters to match the event field in the Schedule
table using the maxlength attribute.

To remove an event the user clicks a button next to the event they wish to remove. This button
calls RemoveEvent.asp, passing in the idSchedule of the event along with the current month and
year so that the link back to Events.asp can be built.

AddEvent.asp

Copy
<!--#includes file="Header.asp"-->
<%
'********************************************************************
' Name: AddEvent.asp
'
' Purpose: Used to add an event to the event database.
'
'********************************************************************

dim dbConn, strSQL

Set dbConn = GetDataConnection


strSQL = "AddEvent '" & Request("nMonth") & "/" & Request("nDay")
strSQL = strSQL & "/" & Request("nYear") & "', '"
strSQL = strSQL & Replace(Request("Event"), "'", "''") & "'"

dbConn.Execute (strSQL)

Response.Redirect("Events.asp?nMonth=" & Request("nMonth") & "&nYear=" &


Request("nYear"))
%>

The AddEvent.asp page takes the information passed in by the form and inserts it into the
database using the AddEvent stored procedure. The page then redirects back to the Add/Remove
Events page so the user immediately sees their new event. Notice how I use the Replace()
function to change single quotes (') to double single quotes (''), which SQL interprets as single
quotes. If you don't do this you will get an error when a user tries to enter an event like "All
Saint's Day."

RemoveEvent.asp

Copy
<!--#includes file="Header.asp"-->
<%
'********************************************************************
' Name: RemoveEvent.asp
'
' Purpose: Used to remove an event from the event database.
'
'********************************************************************

dim dbConn

Set dbConn = GetDataConnection


dbConn.Execute ("DeleteEvent " & Request("idSchedule") )

Response.Redirect("Events.asp?nMonth=" & Request("nMonth") & "&nYear=" &


Request("nYear"))
%>

The RemoveEvent.asp page uses the DeleteEvent stored procedure to remove the given event
ID, and then immediately sends the user back to the Events page.

Performance Issues
Scaling

The beauty of ASP is that it makes building Web pages very easy. However, if you want to build
a site that can scale to a high volume of users, you need to code carefully. In this section I will
discuss various methods to increase the scalability of the Web-based calendar I have presented
here. Although specific to this application, the methods I describe can be used to improve
performance on any ASP Web site.

SQL Optimizations

An easy way to improve the performance of the site is to add an index on the date field of the
Schedule table. This will speed up the GetEvents stored procedure because it looks for events
between given dates.

For small sites, SQL can be installed on the same server as IIS. Once the site starts to grow, you
will want to move SQL to its own server. As the site grows further still, you may want to add
multiple IIS servers that all point to the same SQL server. If traffic to the SQL server grows
excessively, you can partition data onto different servers. You might want to set odd-numbered
months to go to one server and even-numbered months to go to another server. Of course, you
will want to alter your GetDataConnection in Header.asp so it will give you the proper
connection based on the month.

ASP Optimizations

The main optimization for the ASP rendering would be caching pages so they don't have to be
rendered each time. The easiest way to do this is through the ASP Application object. To do
this, you simply save the page HTML into an application variable that has the name of the month
and year (for example, Calendar07-2000). Then, when displaying the Event Calendar page, you
first check to see if the calendar has already been saved in an application variable and, if so,
simply retrieve it. This saves a trip to the SQL box. Here is some pseudo code that shows how
this would work:

Copy
<<do header>>

ShowCalendar(nMonth, nYear)

<<do Footer>>

sub ShowCalendar(nMonth, nYear)

if Application("Calendar" & nMonth & "-" & nYear) = "" then


<<Build Calendar>>
Application("Calendar" & nMonth & "-" & nYear) = <<Calendar>>
End if

Response.Write Application("Calendar" & nMonth & "-" & nYear)


End sub

Of course, when the Events.asp page changes a month's events you will need to empty the
application variable for that month so the changes are reflected.

Security

There are several ways to implement security on this site. For an intranet site, Microsoft
Windows NT®-based authentication is the easiest to set up because your users will most likely
already be logged on to the network. You may wish to let all users view the Event Calendar
page, but only administrators have access to the Add/Remove Events page.

If auditing is a concern, you can easily modify the AddEvent and DeleteEvent procedures to
save their information into an audit table. Alternatively, you can make sure IIS is logging the
query string and user for each page hit. Then it is simple to parse through the logs to determine
who did what and when.

Conclusion
In this article I have shown how to set up a Web-based calendar. My Web-based calendar is very
simple, but it could be easily extended into a full-featured site. I have tried to meticulously
describe the steps I followed in creating my Web-based calendar so that beginning users can see
ASP, SQL, and ADO in action. Finally, I have provided some tips on how to make this site scale
as large as possible. If you find any bugs or have ideas on how I might be able to improve this
code, please send me e-mail at semyan@hotmail.com.

You might also like