All Active Server Pages Tips



A caveat when using ASP's Response.Redirect method

When ASP encounters the Response or End methods, it immediately halts script execution in both the GLOBAL.ASA file and in the application page. As a result, ASP won't execute any script that follows the Redirect method. Instead, it either ends the session or begins processing the new page. For this reason, you should always make the Redirect method the last call in any script.

ZD Tips



Avoid invalid XML characters in ASP pages

If you hard code XML data islands into a Web page, you'll want to avoid several special characters that are part of XML's syntactic structure. XML won't interpret these characters correctly if left within an XML data source. The characters and the alternate character sequences to use in their place are as follows:

<    <
&    &
>    >
"    "
'    '

So, instead of

<Greeting>Hello, 'World'! <This> will bomb!</Greeting>

you'd want to enter

<Greeting>Hello, 'World'! <This> will bomb!</Greeting>

Of course, if you use the XML Document Object Model to create XML nodes, the XMLDOM takes care of this encoding for you. As a result, you won't need to use the alternate characters. So,

MyGreetingNode.Text = "Hello, 'World'! <This> will bomb!"

is perfectly valid.

ZD Tips



Build XML documents graphically with XML Notepad

XML is quickly becoming the data model for most Web applications. However, if you've found yourself cringing at the thought of coding even the smallest XML data island, then the Microsoft XML Notepad is for you. This handy tool provides a nice UI for editing XML documents. With it, you can add nodes, attributes, and values as well as see a graphical representation of the data structure. Even better, XML Notepad takes care of all the actual coding for you. You can download this utility for free from:

http://msdn.microsoft.com/xml/notepad/intro.asp

ZD Tips



Convert ADO fields to XML tags without errors

XML tag names can't contain several special characters or spaces. Therefore, when you use ADO field names as XML tags, make sure to rename the fields, if necessary, in the SQL statement. For example, if you use the following SQL statement:

Select [Employ ID], Name FROM Employees

and then use XMLDOM to convert the recordset fields into XML, the XML document will generate an error. That's because XMLDOM's creation methods convert the [Employ ID] fieldname into <Employ ID>. However, the space is an invalid character. To avoid this error, use an alias name in the SQL string, such as:

Select [Employ ID] AS EmployID, Name FROM Employees

ZD Tips



Create Visual InterDev 6.0 ASP code templates

Instead of retyping the same code lines on virtually every ASP page that you create in Visual InterDev 6.0, simply open Program Files | Microsoft Visual Studio | VIntDev98 | Templates | Web Project Items | New ASP Page.asp file, and then enter the code that you want duplicated, i.e. included files, titles, metatags. Save your work, and any new ASP page that you create will contain the new code.

Will Smith



Ensure accurate string comparisons in ASP pages

As you probably know, the StrComp() function provides a quick way to compare two strings. It takes the following syntax:

StrComp( string1, string2, comparemode)

VBScript compares the two strings according to either the comparemode argument, or the default setting on the server. This function returns 1 if the first string is greater than the second string, 0 if the two are equal, and -1 if the first string is less than the second. However, if you want to compare strings taken from user input, to ensure that the results are accurate, remove any extra spaces from the two strings. For example, you could use something like:

StrComp( Trim(str1), Trim(str2))

Strings with extra spaces will provide inaccurate results. To illustrate, create the following ASP page, and then view it in Internet Explorer.

<html>
<head>
<script language="VBScript">
sub mySort()
Dim str1, str2, ary, sCompare

str1 = document.all.txt1.value
str2 = document.all.txt2.value

Select Case StrComp(trim(str1), trim(str2))
    Case 1: sCompare = "greater than"
    Case 0: sCompare = "equal to"
    Case -1: sCompare = "less than"
End Select

MsgBox str1 & " is " & sCompare & " " & str2
end sub
</script>

<body>
    <form>
        <input type="text" id="txt1" /><br /><br />
        <input type="text" id="txt2" /><br /><br />
        <input type="button" value="Compare" onclick="mySort" />
    </form>
</body>
</html>

First, enter an A; into the first field and a Z; into the second, then click the Compare button. When you do, VBScript informs you that A is less than Z, as you would expect. Now, enter a space before the Z and click the button again. This time the message box inaccurately claims that A is greater than Z.

ZD Tips



Ensure proper remote scripting parameter types in ASP

As you probably know, remote scripting is a great way to access server-side functions and procedures from client-side scripting. However, when you use parameters in a server-side function intended for client-side use, remember that IIS converts all parameter values into strings. As a result, if necessary, you'll want to convert these values back into their proper data type within the server-side function. Also, keep in mind that for security reasons, IIS doesn't let you pass structured data (objects or arrays) as remote scripting parameters.

ZD Tips



Generate accurate ADO RecordCount values in ASP

As you know, the ADO RecordCount property returns the number of records in an ADO recordset. Of course, in several instances, this property also returns a -1 instead. The value RecordCount returns depends on the recordset's cursor type: -1 for a forward- only cursor; the actual count for a static or keyset cursor; and either -1 or the actual count for a dynamic cursor, depending on the data source.

You may be surprised to learn that RecordCount will be -1 for recordsets created with the Execute method from a Connection or Command object. That's because this method generates a forward- only recordset, which, as we mentioned earlier, returns -1.

As an example, enter and run the following procedure in a standard ASP page. When you open it, the page displays -1 for the recordset based on myConRst, and 6246 for myKeyRst.

<%
Dim myConn, myComm, myConRst, myKeyRst
Dim sConnection
sConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
    "Data Source=D:\Microsoft Visual Studio\VB98\Biblio.mdb"

Set myConn = Server.CreateObject("ADODB.Connection")
Set myKeyRst = Server.CreateObject("ADODB.Recordset")

myConn.Open sConnection
myComm = "Select * From Authors"
Set myConRst = myConn.Execute(myComm, , 1)

myKeyRst.Open myComm, myConn, 1
%>

RecCount <BR>
>From Connection: <%=myConRst.RecordCount %><BR>
>From Recordset: <%=myKeyRst.RecordCount%>

<%
Set myKeyRst = Nothing
Set myConRst = Nothing
Set myConn = Nothing
%>

ZD Tips



Globally replace text using just 5 lines of VBScript

If you've ever tried to implement a text search and replace function in an ASP page, you probably resorted to lengthy parsing loops that used Instr() and an entire host of string functions. If so, you'll be glad to know that there's a much easier way.

With the advent of VBScript 5.0, (IIS 5.0) Microsoft introduced the Regular Expression engine. If you've used Perl or JavaScript, you may be familiar with these pattern-matching powerhouses. In a nutshell, regular expressions let you define a pattern, literal or representative, which you can then match against a second string. For example, the literal pattern 'abc' as a regular expression would find a match in 'dabcef', 'abcdef', or 'defabc'. To further refine a regular expression, the Regular Expression engine offers a host of special metacharacters, similar to wildcard characters. For example, using these metacharacters, you could search for any word that began with a letter and ended in a digit. To view these metacharacters and their uses, visit

http://msdn.microsoft.com/scripting/default.htm

then search in the VBScript documentation for the RegExp object's Pattern property. (If you don't have IIS 5.0, all you really need is the latest version of VBScript, which you can download from www.microsoft.com/msdownload/vbscript/scripting.asp)

To create a simple find and replace subroutine with client-side VBScript, first create a RegExp object, like so

<script language="VBScript">
Sub GoReplace()
Set myReg = new RegExp

Next, set the object's properties.

myReg.IgnoreCase = True
myReg.Global = True
myReg.Pattern = "abc"

Here, we've used a literal string to create a global, case- insensitive pattern. Finally, you execute the object's Replace method on a target string, as in

document.all.myTextArea.value = myReg.Replace(document.all.myTextArea, "def")
End Sub
</script>

That's *all* there is to it! This example would replace "abc" with "def" wherever it occurred within myTextArea. To execute the replace on the first matching string only, set the Global property to False.

ZD Tips



Handling multiple Select options with JavaScript

While the HTML Select form control allows multiple selections, you may have wondered how to manipulate those selections, for inclusion in a database, for example. ASP offers several ways to do so. Of course, client-side script and the DOM give you one way to do so. When you use this technique, the basic idea consists of looping through the control's options, check each option's Selected property, and where appropriate, enter the value and text directly into a database or an array, as seen below:

<head>
<script language="JavaScript">

function getSelected() {
var sConnect = "Provider=Microsoft.Jet.OLEDB.3.51;Data " +
  "Source=D:\\Inetpub\\wwwroot\\ZDJindex\\index.mdb"
var adoRst = new ActiveXObject("ADODB.Recordset")
adoRst.open("tblDays", sConnect, 2, 2) //2-dynamic keyset, 2-table command

var objSelect = document.forms["frm1"].elements["sel1"]
var msg = new String("")

//Insert selected items
for (x=0; x<objSelect.length; x++) {
    if (objSelect.options[x].selected) {
        adoRst.AddNew()
        adoRst.Fields("Day") = objSelect.options[x].text
        adoRst.Fields("Value") = objSelect.options[x].value
        adoRst.Update()
        msg += objSelect.options[x].text + ", "
     }
}
adoRst.close()

//Strip the trailing comma
msg = msg.substring(0, msg.length-2)

//Show selected items
alert(msg)
}
</script>

<body>
    <form id="frm1">
        <select size=10 multiple="multiple" id="sel1">
           <option value="1">Sunday</option>
           <option value="2">Monday</option>
           <option value="3">Tuesday</option>
           <option value="4">Wednesday</option>
           <option value="5">Thursday</option>
           <option value="6">Friday</option>
           <option value="7">Saturday</option>
        </select>
        <input type="button" value="Show Selections" onclick="getSelected()">
     </form>
</body>

While this script works just fine on the client-side in Internet Explorer, don't try the same technique when you post a form to server-side ASP. That's because the multiple selections get passed as a comma-delimited string. In an upcoming tip, we'll show you two different ways parse this string on the server side.

ZD Tips



Include VBScript variables in ASP SQL statements

Often, you'll no doubt want to include a VBScript variable in an ASP SQL statement. For example, suppose you want to let a user search a table for names that begin with a letter they specify. To use a variable in a SQL statement, simply concatenate the various parts of the statement together. To see how this works, create an ASP page with the following code:

<HTML>
<BODY>
<FORM Name="test" Action="SQLVars.asp" Method="POST" >
  <INPUT Name="txtSearch" TYPE="TEXT" Size=15 VALUE="SearchForMe">
  <INPUT Type="SUBMIT" VALUE="Submit">
</FORM>
<%
Dim strSQL1
Dim strSQL2
Dim strSearch

strSearch = Request.Form("txtSearch")
If Len(strSearch) Then
        strSQL1 = "Select From Customer(MyField) Where " _
                & "Name(Col.Name) Like 'strSearch%'"

        strSQL2 = "Select From Customer(MyField) Where " _
                & "Name(Col.Name) Like '" & strSearch & "%'"
End If
%>
<UL>
<LI>Before concatenation: <%=strSQL1%>
<LI>After concatenation: <%=strSQL2%>
</UL>
</BODY>
</HTML>

When you run the page, only strSQL2 contains the variable's actual value, which can then be sent on to SQL Server, or any other database that processes SQL statements. Also, notice the use of the single quote before the double quote and after the percent sign. This ensures that the database interprets the variable's value as a string.

ZD Tips



Obtain a header list with ASP's ServerVariables collection

The SeverVariables collection contains all kinds of information about the calling client and the server. For instance, you can determine a visitor's browser type with the HTTP_USER_AGENT variable. Or, you can use HTTP_REFERER to determine the referring Internet address. Not all browsers support the same headers, however. To see a quick list of the headers supported within a browser, run the following code.

<HTML>
<BODY>
<TABLE BORDER=1>
<TH COLSPAN=2>ServerVariables</TH>
<%
For Each var in Request.ServerVariables
  With Response
    .Write("<TR>")
    .Write("<TD><B>" & var & "</B>:</TD>")
    .Write("<TD>" & Request.ServerVariables(var) _
      & "</TD>")
    .Write("</TR>")
  End With
Next
%>
</TABLE>
</BODY>
</HTML>

ZD Tips



Parsing multiple selected options in server-side ASP

In a previous tip, we showed you how to gather multiple selections from an HTML Select element on the client side. However, when you obtain these values after a Get or Post request, you need to use a different technique. That's because these multiple values get passed as a comma-delimited string. So, say you had a Select element named "Lst1" on a form. If you selected three options with values 5, 6, and 7, and submitted the form, then

Request.Form("Lst1")

would contain the string "5, 6, 7". As a result, you'll need to parse this string to get the individual values. To do so, you have two options. First, you can use the Split() function to place the values into an array. Or, if you don't have a version of IIS that supports the Split() function, you can use the Instr() function and search for the comma character within the string. As an example, create an HTML page named GetOptions.html and add the following form to it:

<form id="frm1" action="GetOptions.asp" method="post">
    <select size=10 multiple="multiple" name="Lst1" id="Lst1">
        <option value="1">Sunday</option>
        <option value="2">Monday</option>
        <option value="3">Tuesday</option>
        <option value="4">Wednesday</option>
        <option value="5">Thursday</option>
        <option value="6">Friday</option>
        <option value="7">Saturday</option>
     </select>
     <br /><br /><input type="submit">
</form>

Next, create an ASP page named GetOptions.asp and add the following code:

<%
' Parse request string using Split()
Dim sSelected, arySelected, x
sSelected = Request.Form("Lst1")
response.write("You selected: " & sSelected & "<br />")

response.write("<br /><b>Split()</b><br />")
arySelected = Split(sSelected, ",")
For x = 0 to Ubound(arySelected)
   response.write("Choice " & x & ": " & arySelected(x) & "<br />")
Next

response.write("<br /><b>Instr()</b><br />")

' Parse request string using Instr()
Dim subString
x = 0
sSelected = sSelected & ","

Do Until Instr(sSelected,",") = 0
    response.write("Choice " & x & ": " & Left(sSelected, _
       instr(sSelected,",") -1) & "<br />")
    sSelected = Mid(sSelected, instr(sSelected,",") + 1)
    x=x+1
Loop
%>

Note, that the same techniques would work with Response.QueryString("Lst1") as well.

ZD Tips



Quickly determine client browser types in JavaScript code

The document object model and ASP pages offer several ways to determine a client's browser type. Most, however involve long parsing routines that search for specific substrings within a larger string. Fortunately, using JavaScript, there's a quick way to determine if the client browser is either Netscape Navigator 4+ or Internet Explorer 4+. The basic idea is that you test for objects in the browser's DOM that don't exist in the other browser's DOM. For example, IE 4.0 + browsers include the document.all collection, while NN4.0 + browsers support the document.layers collection. If one of these objects is null, then your code can infer that the client is the other browser type. For example, the following script displays the boolean results of each test when you load a Web page:

<script language="JavaScript">

  var nav4 = !(document.layers == null)
  var iex4 = !(document.all == null)

  alert("Nav: " + nav4 + " IE4: " + iex4)
</script>

As you can see, the first expression sets the nav4 variable equal to the opposite of document.layers==null. So, if you view this page in an IE 4+ browser, document.layers is null, and the entire expression evaluates to false.

ZD Tips



Register WSC scripts before using them in ASP

The Windows Scripting Component is a great tool that let's you create COM components for use in ASP pages. What's more, you can use either VBScript or JavaScript to give them functionality. When you create a WSC component, however, you must register it before you can use it in an ASP page. To do so, open Windows Explorer and right-click on the WSC file you just created. Select Register from the shortcut menu. To create an object variable based on the new script object, use code similar to

Set objXMLCreate = Server.CreateObject("MyScriptObj.WSC")

At this point, you're free to access any of the object's methods and properties.

ZD Tips



Searching R Computers Tips

To preform effective searches you can use the following techniques:

To search all tips for a word, for example the word macro, go to the index, type macro and click Go. The Search Results will contain the titles of all tips that contain the word macro. If you would like to limit your search to only the Excel tips, click the ‘Excel' link and preform your search from the Excel titles page instead.

If you enter more than one word in the search box, for example the words excel macro, then your search will include tips that have the word ‘excel' in them, or the word ‘macro', or contain both words ‘excel' and ‘macro'. This is the same as if you had typed excel or macro. If you only want tips that contain both words ‘excel' and ‘macro' then include the word ‘and' between the word, like excel and macro.

And finally, if you want to search for a phrase, such as ‘excel macro' then include the phrase in double quotes, "excel macro". This search will find only tips that contain both words right next to each other in the order listed.

You may combine any of the techniques listed above in one search.

Robert Price



Setting checkbox values from an Access database

Often you'll want to display a checkbox value stored in an Access database in an ASP page. Depending on the setting in your Access table, Access may display Yes/No, On/Off, or True/False in the field when you view the table in the database. As a result, you may think to use ASP similar to

<input type="checkbox" name="chk1" value="Yes" 
<% if rs("checkfield")="yes" then %>
  checked="checked" 
<% end if %> />

However, this doesn't actually work. That's because even though Access displays the field contents as a Yes or No, it stores the contents as True or False, (-1 and 0 respectively). To get an accurate checkbox setting in ASP, use

<input type="checkbox" name="chk1" value="Yes" 
<% if rs("checkfield")=True then %>
  checked="checked" 
<% end if %> />

ZD Tips



Simplify loading stored values via ASP

When loading an <OPTIONS> list from a database table, it's much easier to call a procedure that uses process parameters. This way, you can use the same procedure for several different operations. For example, suppose you want to fill a Listbox with a list of animals. In addition, you've set up several checkboxes on a Web page that let the user simply view the list, or load the list with one of the animals already selected. The following example shows how you might process the resulting page. (To save space, we hard-coded the two parameters.)

<!-- #include File="DBConnect.Asp" -->
<HTML>
<BODY>
<FORM>
<SELECT name=Atype size= 5>

<%
Dim chkMode
chkMode = 2  'or Request.Form("chkMode")
fillOptionList chkMode,"Snake"
%>
</SELECT>

<%
Sub fillOptionList(myMode, optionValue)

Dim rsAnimal
Dim strSelected

  set rsAnimal = CreateObject("ADODB.recordset")
  With rsAnimal
    .Open "tblAnimals", strDB, adOpenStatic,,adCmdTable

    Do While Not .EOF
       Select Case myMode
          Case 1
            strSelected = ""
          Case Else
            If optionValue = rsAnimal("Animal") Then
              strSelected = " SELECTED"
            Else
              strSelected = ""
            End if
       End Select

       Response.Write("<OPTION" & strSelected & " VALUE=" _
          & rsAnimal("ID") & ">" & rsAnimal("Animal") & "</OPTION>")
       .MoveNext
       Loop

       .Close
    End With
  Set rsAnimal = Nothing
End Sub
%>

</BODY>
</HTML>

For the OPTION elements, this code produces output HTML like this:
<SELECT name=Atype size= 5>

<OPTION Value=1>Cat</OPTION>
<OPTION Value=2>Cow</OPTION>
<OPTION Value=3>Dog</OPTION>
<OPTION SELECTED Value=4>Snake</OPTION>
<OPTION Value=5>Elephant</OPTION>
<OPTION Value=6>Fish</OPTION>

</SELECT>

Faisal Ladak



Syntax requirements for integrating XSL into ASP and HTML

Since an XSL stylesheet is an XML document itself, its markup must conform to XML grammar rules. Most notably, you must ensure that you close all tags. Since HTML is considerably more forgiving in this regard, make sure that the markup in XSL sheets will successfully parse. For example, to use <BR> to express a line break, you must enter <BR/> instead. To read more about the W3's recommendation for XHTML, which addresses this issue, see:

http://www.w3.org/TR/xhtml1/

ZD Tips



Use a single ADO connection to reduce ASP server load

If you need to execute multiple SQL statements on a single database in a single ASP page, it's often wise to open a single Connection and reuse it multiple times. Doing so reduces the number of times the server must open and close the same database, which can significantly increase the server's load. To use a single connection, create the database Connection at the beginning of the page, then destroy it at the end. When you Execute a SQL statement, whether it returns a Recordset or not, specify the active Connection. Here's an example.

<%
strDSN  = "DSN=database;UID=username;PWD=password"

Set conn = Server.CreateObject("ADODB.Connection")
conn.Open strDSN

strSQL = "select column from table"

Set rsResults=conn.Execute(strSQL, , 1)

if not rsResults.eof then
        temp = rsResults("column")
else
        temp = "No Results"
end if

'close the Recordset, but leave the Connection open
rsResults.Close

strSQL = "delete from table where column=123"
conn.Execute strSQL, , 1

'Done executing SQL statements at this point, so close the Connection.
conn.Close

set rsResults = Nothing
set conn = Nothing
%>

Brian Coverstone



Use ADO's native OLEDB drivers instead of ODBC

When you create an connection string, ADO gives you a choice between indicating a data source driver as either a Driver, as in

Driver={SQL Server};DBQ=database_file

or a Provider, such as

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=database_name

However, when you use the first option, ADO uses older ODBC drivers to connect to the data source; whereas the second form uses OLEDB, which is ADO's native data access interface. For this reason, you should use the Provider option whenever possible. Such native OLEDB drivers exist for SQL Server, Index Server, Site Server Search, and Oracle, among others.

ZD Tips



Why relative filespecs may not work in ASP

Even though the helpfile states you can use relative directory paths with FileSystemObject objects, you probably encountered an error if you tried to use them in an ASP path. That's because the directory that contains the ASP page doesn't become the current directory, as far as the FileSystemObject is concerned. To illustrate, run the following VBScript code in an ASP page:

<%
Set FileObject = Server.CreateObject("Scripting.FileSystemObject")
filespec="\test.jpg"
CurrDir = FileObject.GetAbsolutePathName(".")
response.write "Using CurrDir: " & CurrDir & filespec & "<br>"
if FileObject.FileExists(filespec) then
  response.write "[CurrDir] File Found<br>"
else
  response.write "[CurrDir] No File found<br>"
end if

response.write "Using MapPath: " & Server.MapPath(filespec) & "<BR>"
if FileObject.FileExists(Server.MapPath(filespec)) then
  response.write "[MapPath] File Found<br>"
else
  response.write "[MapPath] No File found<br>"
end if

Set FileObject = Nothing
%>

Michael Harris