Active Server PAges Tips


Persistant Radio Buttons

ASP pages are often used to both display a form, and carry out the action once the form is submitted. One of the most annoying tasks of HTML/ASP forms programing is keeping a user's chosen radio buttons selected when redrawing the form after it has been submitted. The following code is one way to create a one ASP page form that has persistent radio buttons:

<HTML>
<HEAD><TITLE>Pick a color</TITLE></HEAD>
<BODY BgColor=<%= Request.Form("Color")%>>
<%
RedChecked = ""
BlueChecked = ""
YellowChecked = ""

SELECT CASE Request.Form("Color")
CASE "Red"
RedChecked = "CHECKED"
CASE "Blue"
BlueChecked = "CHECKED"
CASE "Yellow"
YellowChecked = "CHECKED"
END SELECT
%>
Pick a color:<BR>
<FORM Method=Post>
Red: <INPUT Type=Radio Name=Color Value=Red <%= RedChecked%>>
Blue: <INPUT Type=Radio Name=Color Value=Blue <%= BlueChecked%>>
Yellow: <INPUT Type=Radio Name=Color Value=Yellow <%= YellowChecked%>>
<BR>
<INPUT Type=Submit>
</FORM>
</BODY>
</HTML>

Status Codes

When a server responds to an HTTP request, the first line it returns is the status line. This line contains a three-digit code and a short description of the status of the response. There are five classes of codes, explained in the following list:

1## - Informational.  These codes are mainly experimental.

2## - Success.  The codes in this class are returned on successfully filled requests. Status code 200 is used to indicate a successfully retrieved web page.

3## - Redirection.  The status codes in this class are used to show that additional action must be taken before the request can be satisfied. For example, code 301 can be used to indicate that a page has been moved and the browser may be redirected to the new page.

4## - Client Error.  These codes are returned when a browser has made a request that can't be fulfilled. The dreaded "404--URL not found" is perhaps the most famous of status codes.

5## - Server Error.  This class of status codes is used to indicate a problem on the server end. Sometimes code 503 is used to indicate a server currently has too many requests to process.

Knowing the status code classifications can sometimes make debugging web-page problems less difficult.

Using Transactions to bullet proof your database interactions

As web pages begin to rely more and more on databases, it is important you write code that is aware of the sucesse or failure of SQL statements. By grouping connected database interactions into Transactions, you can ensure that if any statement fails, none of the statements in the Transaction will be processed. This is useful in situations where you are updating two tables, and don't want one to fail and the other to succeed. 

The following code shows how to group two SQL statements into a transaction:

<%
Set MyConn=Server.CreateObject("ADODB.Connection")
MyConn.Open "FILEDSN=C:\Program Files\Common Files\ODBC\Data
Sources\JupiterData.dsn"

MyConn.BeginTrans
MyConn.Execute("UPDATE YourAccount SET Balance=Balance+100 WHERE Account='1'")
MyConn.Execute("UPDATE MyAccount SET Balance=Balance-100 WHERE Account='1'")
MyConn.CommitTrans
MyConn.Close
%>

Rating the content of your web site

You can quickly and easily place ratings on any web pages you feel may have content not suitable for children. These ratings, when combined with a
properly configured web browser, can prevent unsuitable viewers from looking at your web site.

To rate a web page, right click on the page in Internet Service Manager and from the pop-up menu, click Properties. In the dialog box displayed, select
HTTP Headers and click on Edit Ratings... to launch the Content Rating dialog. Select the Ratings tab and click on the Enable Ratings for this resource checkbox.
You then need to rate your page in each of the four Recreational Software Advisory Council (RASC) categories: violence, nudity, sex, and language.
Highlight the category and use the slider to rate your page. Finish by entering your name and the date.

Using authorization headers

One of the advantages of requiring user authentication is that you can use the logon information in your Active Server Page (ASP). The following code
comes from a page that requires user authentication:

Your name is

This simple ASP displays the name of the user who has been authenticated by the web server. You can use this to give your ASP a personalized feel, or
to change what information is displayed depending on the user.

Controlling How a Page is Cached

A proxy server is used to reduce the amount of time spent retrieving documents over the Internet. It does this by caching, or storing, the document in memory and then serving it from memory the next time a client tries to retrieve the page. This can cause problems with Active Server Pages because of their dynamic nature.
By default, IIS sends web pages with headers that tell proxy servers not to cache their documents. If you need to change this, you can by placing the
following line of code at the top of your ASP page:

<% Response.CacheControl="Public" %>

This will allow all proxy servers that retrieve the page to save it in their local memory and improve the speed at which it can be retrieved.

Q. How do I send mail from an ASP page?

Tom: There are a several ways to do this. The best right now is to use CDO (Collaboration Data Objects) for NTS, which is basically a lightweight version of the CDO for Exchange. In the distant past, with Internet Information Server 3.0, some people used the Microsoft Personalization System SendMail component from Site Server 2.0 to send mail. However, with CDO is built into IIS 4.0, so you get it for free with the NT Option Pack. You can also do things like send MIME encoded messages, which was unavailable with the older SendMail object. For all intents and purposes, think of CDO for NTS as replacing the SendMail object.

At a minimal level, you can send mail from an ASP page using CDO in about four lines:

<%
Dim myCDO
Set myCDO = Server.CreateObject("CDONTS.NewMail") 
myCDO.Send "From@importantcustomer.com",
  "servin@microsoft.com","Servin It Up","Love your column.
  The Web Men are cool, too."
Set myCDO = nothing 
%>

Just replace your e-mail address in the "from@importantcustomer.com" section and run the above code. I set the myCDO object to nothing at the end, since it can only be used once, and needs to be recreated every time a message is sent.

You might want to use IF IsObject(CDO) == FALSE to determine if the object was created correctly, as well as do any other error checking that might be important to you. You can also set each parameter individually, instead of passing them all together as I did. Parameters available are the usual e-mail parameters of to:, importance, subject, file attachments, body, etc.

If this doesn't work upon first try, you probably need to go into the Microsoft Management Console (MMC) and ensure that you have correctly installed the SMTP (Simple Mail Transfer Protocol) service. The SMTP service is installed by default for IIS 4.0, so you should at least have it installed. And contrary to popular opinion, you do not need to have Exchange installed. In fact, as long as the SMTP Service is running on your server, it can point to any valid SMTP server.

Image maps 101

To create precise link areas within a graphic on a web page, many web developers use image maps. If it's important to make your image maps
compatible with a wide range of browsers, you should probably use server-side image maps, which require you to use both the ISMAP attribute
of the IMG tag on the client side and to create a MAP file on the server side. For example, to supply a map file named MAPFILE.MAP for an image
named IMAGE.GIF, you'd use the following HTML description

<A HREF="/directory/MAPFILE.MAP"><IMG SRC="IMAGE.GIF" ISMAP></A>

The map file itself is simply a text file that provides the attributes of the image map in question. For example, the map file definition

rect /OTHERPAGE.HTM 0,0 45,45

creates a rectangular hot spot on the image, starting in the upper-left corner and terminating at pixel location 45,45.

Controlling Anonymous page requests

If the Allow Anonymous box is checked in the IIS Service Manager dialog, IIS will always attempt to access the requested resource by impersonating
the Anonymous Logon account (by default, IUSR_machinename). The IUSR_machinename account has a randomly generated password created by the
installation process; this password is then added to the Guests group and given guest privileges.

Adding or removing the Allow Anonymous check is the best way to turn on or off anonymous access for the entire Web server. With Allow Anonymous
deselected, only users with valid, verifiable (using either Basic or Challenge/Response authentication) Windows NT accounts will be serviced.
Setting up IIS this way is usually appropriate for a corporate or members-only setting, where it's important to validate all users accessing your site.

Authenticating Anonymous requests

By default, when a browser requests a Web page, IIS will first try to fill the request without authenticating the user. In order to do this, IIS impersonates a special Windows NT account, named IUSR_machinename (where machinename is the name of the IIS host computer). When you install IIS, the installation program creates this account automatically. If, by impersonating the IUSR_machinename account, IIS can access the requested resource, then it serves the page to the anonymous user; otherwise, the user gets a 401 error.

A common problem with anonymous access occurs when the password for the IUSR_machinename account and the password entered in the Internet Service Manager get out of sync. When IIS tries to impersonate the IUSR_machinename account, it submits the password that was entered in the anonymous logon field to a Windows NT server. If that password is incorrect, IIS is prevented from using the IUSR_machinename account. Once anonymous access fails, IIS will attempt to authenticate everyone. Because authentication can happen silently, the site can fail, but the reason for failure isn't always apparent. The type of authentication you're using makes a huge difference if your pages are accessing other resources, such as databases
or server-side components (DLLs).

ASP Code-Based Security

Using ASP code, you can implement more specialized security for your site.
For example, say some annoying users plague your site. Because their IP addresses can be pulled from the server activity logs, you could use the
following code to deny access:

<%If request.servervariables("REMOTE_ADDR") = "200.200.157.4" then
    Response.Buffer = TRUE
    Response.Status = ("401 Unauthorized")
    Response.End
End If%>
       
There are many variables available within an Active Server Page that supply information about the browser making the request, as well as the information about IIS itself. The LOGON_USER command, for example, will return the Domain\Username of authenticated users, and a blank for anonymous users. You could then use server-side code to check for specific individuals, and redirect them to other pages.

Batch your code to save processing time

If you use the <%=...%> syntax to write in multiple places in your code, consider "batching" those writes by replacing multiple, interspersed

<%=...%> writes with one Response.Write statement. While you are making that change, take a look at how you have your HTML code with regard to your script.

Try not to intersperse HTML and script too much; instead, try to have blocks of script and blocks of HTML. Arranging your HTML and Script code
will save you valuable server process time.

Manage sessions individually in IIS4

If you're an experienced developer, you're probably using Session object to store information that you need for a particular user-session. As you know,
variables that are stored in the Session object are not discarded when the user jumps between pages in the application; instead, these variables persist for the entire user-session. The Web server automatically creates a Session object when a user (who does not already have a session) requests a Web page from the application. The server destroys the Session object when the session expires or is abandoned.

To avoid this, you can turn off the Session feature; however, you can't turn off the Session feature on a per application basis in IIS 3.0. Turning it off for the entire server is faster but drops a lot of functionality. Instead, be very careful to use the Session object only when you really need to. If you use the Session object at all in your application, be sure to use it as soon as possible, so you can avoid the Session object from being reset. The best solution is to use IIS 4.0, since you can enable the session state on a per-application basis and it can be disabled for specified .asp files.

Debug applications in IIS4

Internet Information Server (IIS) 4.0 now enables you to debug the Global.asa file, .asp files, .cdx files, and ActiveX components written in Java. With IIS 3.0, debugging usually meant typing in Response.Write statements, which would send the necessary information to the browser to determine scripting errors. Using the new Microsoft Script Debugger that ships with IIS 4.0 and Internet Explorer 4.0 it is possible to debug client-side and server-side scripts. To maximize performance, debugging is not enabled by default for ASP-based applications, so you'll have to do it manually. Remember, never enable debugging for an application in production, that is, a site being used by others.

To enable debugging, click the Configuration button on the application's Properties page. Under the Application Debugging tab, select the Enable ASP
server-side script debugging check box. Click OK in both dialog boxes to save your application's settings. Now debugging is enables for this application. To debug a page, simply open it in your browser. Now start Script debugger for the Windows Start menu. The script debugger will automatically open the page for you.

Using Notepad with .Asp Files

Here is a tip about using Notepad to create .asp files:
In the Save or Save As dialog boxes,
if the Save As Type box displays Text Documents (*.txt), the file name extension .txt is added to whatever you type in the File Name box.
So, if you type Myfile.asp in the File Name box, the saved text file is actually named Myfile.Asp.txt.

To avoid this, select All Files in the Save As Type list, or enclose the file name in quotation marks before saving.

Installing ASP on a Windows NT Backup Domain Controller

If you installed Microsoft Internet Information Server as part of installing Microsoft Windows NT Server, and you made your computer a Backup Domain Controller during Windows NT setup, you will receive an error message when you install ASP.

To successfully install ASP under these conditions:
Select Active Server Pages Uninstall from the Microsoft Internet Server (Common) Program Group in order to remove ASP.
Reinstall IIS.
Reinstall ASP.

Server-Side vs. Client-Side Scripting

When you create a dynamic html page the code that makes the changes to the web page must be run in one of two places. It can be client-side code
executed by the user's web browser, or it can be server-side code executed by the server. There are advantages and disadvantages to using one over the
other, and a well-planned mix of the two can have a dramatic effect on your web page.

The advantages of server-side scripting are many. Because all of the server side code is executed before the HTML is sent to the browser, your code is
hidden. Server-side code is also the only choice if you want to access files and directories on the local machine. Server-side code is also browser independent. Because the HTML code returned by the server is simple HTML, you do not have to worry about the version of browser the client is using. The disadvantage to server-side scripting is that the server must use valuable resources to parse each page it sends out. This could slow down your web site.

Client-side scripting can be very useful. The major advantage is that each web browser uses its own resources to execute the code found on the web
page. This eases the burden on the server. The disadvantages are that you can not prevent the user from seeing your code and that you can not use
client-side code to access local files, directories, or databases.

By designing your web site to take advantage of the strengths and weaknesses of both client-side and server-side scripting, you can protect your code and get maximum performance.

Multifaceted image maps

While you may think of server-side image maps as being limited in flexibility, you can actually identify complex shapes as image hot spots. Take a look at the following map file definitions, creating a rectangle, circle, polygon, and even an individual point.

#50x50 pixel rectangle starting at 0,0
rect /page.htm 0,0 50,50

#circle with 40 pixel radius starting at 50,50
circle /page.htm 50,50 40

#polygon with 3 vertices
poly /page.htm 15,15 15,75 50,45

#individual point-great for "easter egg"
point /page.htm 100,100

IIS and complex polygons

You'll probably never encounter this problem, but it's one you should know about. If you create server-side area maps for IIS, there's an upper limit on the number of vertices you can specify. Early versions of IIS respond with an access violation if you supply more than 100 points; the current version will break at 160. So, if you're planning to map out all the surface characteristics of a particularly complex shape, count your points carefully.

Variable Name Prefixes

Good ASP code is easy to read and understand. A quick way to make your code self-documenting is to name your variables in a meaningful way. The IIS
Resource Kit team has put together a list of variable name prefixes to be used with assorted data types. Using them will not only make your code easy
to read, but it will also have a professional feel.

The prefixes are as follows:

    bln       Boolean
    byt       Byte
    col       Collection object
    cur       Currency
    dtm      Date-time
    dbl        Double
    err        error
    int         Integer
    lng        Long
    obj        Object
    sng       Single
    str        String
    udt       User-defined type
    vnt        Variant
    cmm    ADO command
    cnn      ADO connection
    fld        ADO field
    prm      ADO parameter
    rst        ADO recordset

Simply add the prefixes to the front of your variables. For example, the variable Today becomes dtmToday. This simple habit can save you time and
energy.

No blank spaces for DSN

When creating a DSN using the ODBC Manager, make sure there are no spaces on the DSN. For example, Test DSN should be TestDSN. Referencing Test DSN in an ASP will result in the following error:

Error 80004005:Data source name not found and no default driver specified

Caching an ASP page

Some applications send pages through a proxy server, which acts on the behalf of client browsers to request pages from a Web site. In most instances the proxy server caches HTML pages to reduce the load on the server, and to improve the processing speed of the HTTP request. This usually works well for static content but is inappropriate for most dynamically generated ASP pages. You can, however, instruct a proxy server to cache an ASP page by setting the Response.CacheControl property to Public. By default the property is set to Private, which prevents the server from caching the page.

<% Response.CacheControl = "Public" %>

Debugging - viewing values

When printing to the screen, using the print statement can be helpful for debugging a group of SQL statements. If however, you just want to check the value of a variable to help in a debugging process, you don't need to use PRINT. You can use the SELECT statement. By using SELECT, you don't need to worry about converting the variable to a character datatype to print it.

Mapping the virtual path of a file

If you want to map the virtual path of a file to its physical path, you can use the following designation:

PhysicalPath=Server.MapPath("/mydir/test.txt")

When the virtual directory named mydir has the physical path c:\mydir then MapPath("/mydir/test.txt") would return the value c:\mydir\test.txt.

Redirecting made easier

When the Web server processes an HTTP request, it returns the HTML to your browser as it processes the ASP page. You can however, set the buffer property of the Response object to TRUE so that the page will be processed in its entirety before any HTML is returned to the client. This is helpful if you need to redirect a user to another page in the middle of processing. You use the Response.Clear method to clear the contents of the buffer before you redirect the user. In fact, you may have already run into the problem where a property or method requires that you set the buffer property to TRUE to prevent the Web server from returning the HTTP header before a script can modify the header. This is most commonly seen in ASP pages that redirect the user to another page.

<%
Response.Buffer = True
%>
<HTML>
<BODY>

<%
If Request("Smode") = 1 then
Response.Clear
Response.Redirect "/test/home.asp"
End If
%>
</BODY>
<HTML>

Setting the regional settings for your computer

You can change the short and long date formats in the Regional Settings in your Control Panel. To display a date according to your computer's Regional Settings, use the FORMATDATETIME() function.

TRUNCATE TABLE versus DELETE

When trying to improve speed and eliminate information in the log file, use TRUNCATE TABLE instead of DELETE. When you use DELETE, row deletions are logged. This increases the size of the log file and is slower than using TRUNCATE TABLE.

Switching to Design view after modifying ASP script in Visual InterDev

When developing an Active Server site using Visual InterDev6 you may have encountered the annoying problem of not being able to switch the editor into Design view after you have modified the ASP script. The Visual InterDev editor can't switch into Design view because there is unquoted ASP script inside of an attribute value or inside of a <select> tag. The problem is that the Design Editor doesn't know how to handle ASP script within certain HTML tags.  Inserting the code
below into an ASP page from the Visual InterDev source Editor and then switching to Design view will demonstrate this problem:

<SELECT>
<OPTION value="<%=Value1%>">First Option</OPTION>
</SELECT>

To get around this problem, you need to use the Response.Write method to write out the HTML that contains the embedded ASP.  You will then be able to switch to Design view. The HTML control however will not appear on the page. The code below demonstrates how to accomplish this.

<SELECT>
<%
Response.Write "<OPTION value=" & Value1 & "> First Option</OPTION>"
%>
</SELECT>

Using the Response.IsClientConnected property to determine whether
or not the browser is still connected to the server


When a browser requests an ASP page from the Web Server, but does not wait for the entire page to be downloaded, the server continues to process the request, wasting valuable CPU cycles.  If your Web Server is Internet Information Server (IIS) 4.0 you can use the Response.IsClientConnected property to determine whether or not the browser is still connected to the server.  If it is not connected to the server you can stop processing to conserve CPU cycles. If you request an ASP page that contains the script below and use PerfMon to monitor the CPU cycles on the Web server, you will notice that if you click stop in the browser, the number of CPU cycles will decrease sooner than if the loop had continued.

<%@ LANGUAGE="VBSCRIPT" %>
<%
Function IsConnectedAfter(Seconds)
Dim StartTime
Dim PauseTime

IsConnectedAfter = True
StartTime = Now

Do While DateDiff("s", StartTime, Now) < Seconds
PauseTime = Now
Do While DateDiff("s", PauseTime, Now) < 1
'Do Nothing
Loop
Response.Write "."
If Response.IsClientConnected = False then
IsConnectedAfter = False
Exit Function
End If

Loop
End Function
%>

Enhancing browser page load performance

If your ASP application is experiencing browser page load performance problems you may want to consider implementing one or both of the following techniques.  First, a fairly easy way to improve the speed performance of an ASP page is to set the @ENABLESESSIONSTATE to False if an ASP page does not use any session variables.  To accomplish this you need to insert the following line of code at the top of the ASP page.

<%@ENABLESESSIONSTATE = False%>

Second, you can also improve the performance of a page by copying the values of collection variables into local variables as opposed to referencing the object each time you need the variable value.  For example, you may need to reference the Request.ServerVariable collection to determine the user's logon id.  To accomplish this you use the following line of script.

Request.ServerVariables("LOGON_USER")

If you need to use this value in several places on your page, it is much more efficient to store this value to a local variable and then reference the local variable.

<%
Dim User
User = Request.ServerVariables("LOGON_USER")
Request.Write User
%>


Legal Disclaimer
THE INFORMATION IN THIS PUBLICATION IS PROVIDED "AS IS". WE EXPRESSLY DISCLAIMS ALL REPRESENTATIONS AND WARRANTIES OF ANY KIND REGARDING THE CONTENTS OR USE OF THE INFORMATION INCLUDING, BUT NOT LIMITED TO, EXPRESS AND IMPLIED WARRANTIES OF ACCURACY, COMPLETENESS, MERCHANTABILITY, FITNESS FOR A PARTICULAR USE, OR NON-INFRINGEMENT. IN NO EVENT SHALL WE BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, LOST BUSINESS OR LOST DATA, RESULTING FROM THE USE OR RELIANCE UPON THE INFORMATION, EVEN IF WE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU.