Detecting When Exceptions Occur

To be able to handle errors gracefully, it is imperative that some mechanism exists to inform us developers when an error arises. Errors occurring in an ASP page can be detected in one of two ways: through the scripting language’s error-handling interface, or through ASP 3.0’s new ASPError object.

The VBScript and JScript 5.0 scripting engines both contain robust runtime error-detection mechanisms. ASP pages (or other scripts) created using either of these scripting languages can use the scripting language’s inherent error-handling capabilities to detect when errors occur. As we’ll see in Section 3.2.1, using either VBScript’s or JScript’s error-handling mechanisms often results in verbose, inelegant, and unreadable code when compared to the elegance of the ASPError object.

The ASPError object, which we’ll detail in Section 3.2.2, provides detailed information about an error that just occurred in an ASP page, including a description and line number. However, the ASPError object can only be used with IIS 5.0/ASP 3.0, which, of course, requires Windows 2000 as the web server. Therefore, if you are using Windows NT as your web server’s operating system, you must rely on the scripting languages’ error-handling techniques to detect and gracefully respond to exceptions.

If you are using Windows 2000, though, you are in luck. To use the ASPError object, a separate error-handling web page is needed. This separate page is responsible for receiving the detailed error information and providing an understandable error message to the end user. Using this approach, an error that occurs on any line in any ASP page will result in a call to the error-handling web page. Furthermore, the ASPError object provides more detailed information on the error that occurred than either of the VBScript or JScript error-handling objects.

Warning

Using the ASPError object approach alone makes it next to impossible to detect an error, circumvent it, and continue processing. Once an error-handling web page is set up, when an error occurs, the user is sent to the error-handling web page via a Server.Transfer. Therefore, you can’t fix the error on the error-handling web page and resume processing on the ASP page where the error originated. We’ll look at the ASPError object in finer detail later in this chapter in Section 3.2.2.

Detecting Exceptions with Scripting Language Error-Handling Mechanisms

Both the VBScript and JScript 5.0 scripting engines provide runtime error-handling routines to assist in detecting and gracefully handling implementation errors. VBScript’s error handling is very similar to Visual Basic’s, using the On Error Resume Next notation and the Err object. JScript’s error handling is similar to C++’s and Java’s, using try ... catch blocks. Regardless of the scripting language used, providing adequate error handling usually results in bloating one’s code severely.

If your web site is not running on IIS 5.0, then unfortunately, you do not have access to the ASPError object, and therefore must rely on the techniques discussed in this section to detect errors. If, however, you are using IIS 5.0, and all you plan on doing when an error occurs is displaying a friendly error message to the end user, then it is highly recommended that you rely on the error handling provided by the new ASP 3.0 ASPError object.

The main advantage the scripting language error-handling techniques have over the ASPError object is the ability to recover from an error. Using these techniques, a developer can detect when an error occurs and decide on some alternative course of action, keeping the script running smoothly from the perspective of the end user.

Warning

VBScript and JScript error-handling mechanisms can only detect runtime errors. You cannot use these techniques to detect, recover from, or display readable error messages about compile-time errors.

Detecting errors with VBScript

If you are familiar with error handling in Visual Basic, you’ll find VBScript error handling easy to pick up. By default, error handling is disabled. This means if an error occurs during the execution of a VBScript script, the script is halted and the user is presented with an error message. Usually these error messages are quite cryptic and daunting for the end user. Imagine a visitor to your web site who is presented with an error similar to:

Server object error 'ASP 0177 : 800401f3' 

Server.CreateObject Failed 

/SomePage.asp, line 14 

Invalid class string

Would you expect this customer to return to your site in the future? This daunting error message could be modified to a more friendly error message that is less likely to scare the user away. To be able to determine when an error occurs in a script, though, error handling must be enabled.

In VBScript, error handling is enabled and disabled using the On Error statement. To enable error handling, enter the following command at the top of your ASP page:

                  On Error Resume Next

This informs the scripting engine that when an error occurs, it should proceed to the next line of code rather than abruptly stopping and displaying an error message. To disable error handling, use the following statement:

                  On Error Goto 0

Simply enabling error handling is not enough to detect when an error occurs, however. After each statement that might cause an error, an If statement needs to be used to determine whether or not an error did occur. This technique is known as

inline error handling. I find this constant inquiring whether or not an error has occurred to be rather verbose and annoying, and liken it to an inefficient manager.

Imagine that you are a manager for one employee. This employee performs a number of tasks, and as a manager, it is your job to ensure that these tasks do not cause any errors. After each task this employee performs that might cause an error, you take a moment out of your schedule to ask the employee whether or not an error occurred. Such a model is far from efficient and is very verbose, containing many unneeded communications between manager and employee. Ideally, the employee would know when an error occurs, and would be able to approach you, the manager, when something has gone awry. However, with VBScript and JScript error handling, we do not have this option, and must continually be bothered with having to inquire whether or not an error has occurred.

Tip

How often should you, the manager, ask your employee if an error has occurred? Ideally, after every statement that might generate an error, the employee should be queried if an error occurred. Of course, what statements might generate an error? Deciding when to check for an error is not always easy. This topic is discussed in greater detail in Section 3.2.1.2, next.

Example 3.1 contains an example of error handling. Note that at the start of the script, On Error Resume Next is issued, enabling error handling. Then, after each statement that might cause an error, a conditional statement is used to determine whether or not an error has occurred. If an error has occurred, a short error message is presented to the visitor.

Example 3-1. Using VBScript to Detect an Error

<%@ LANGUAGE = "VBSCRIPT" %>
<% Option Explicit %>
<%
  'Enable error handling
  On Error Resume Next

  'Create two objects
  Dim objConn, objRS
  Set objConn = Server.CreateObject("ADODB.Connection")

  'Check to see if an error occurred
  If Err.Number <> 0 then
    Response.Write "Error in creating Connection object.<BR>"
    Response.Write "Description: " & Err.Description
    Response.End
  End If

' The ProgID is invalid, so this line should generate an error  
Set objRS = Server.CreateObject("Database Recordset")

  'Check to see if an error occurred
  If Err.Number <> 0 then
    Response.Write "Error in creating Recordset object.<BR>"
    Response.Write "Description: " & Err.Description
    Response.End
  End If

  'If we've reached here, no errors!
  Set objRS = Nothing
  Set objConn = Nothing  
%>

VBScript provides an Err object to handle runtime errors. When error handling is enabled and an error occurs, the Err object’s five properties are automatically populated with the error information from the latest error. These properties are presented in Table 3.1.

Table 3-1. The Err Object’s Properties

Property

Description

Number

A numeric value or code uniquely identifying the error

Source

The name of the application or object that generated the error

Description

A lengthy description of the error

HelpFile

A fully qualified path to a help file

HelpContext

A context ID for a topic in a help file

Tip

To determine whether an error has just occurred, check the Number property of the Err object. If no error has occurred, this property will equal zero. If an error has occurred, the property’s value will be unequal to (i.e., either greater than or less than) zero.

The Err object contains two methods: Clear and Raise. The Clear method simply resets all of the property values. If you plan on trying to recover from an error, you will need to use the Clear method once you detect an error and find some alternative path around the error. If the Clear method is not used, the next time we check Err.Number we will find it is not equal to zero (since it still equals the value from our first error). Therefore, if you plan on continuing execution after handling an error, be sure to issue an Err.Clear after recovering from each error. The following code snippet presents a case when you’d use the Clear method:

If Err.Number = SomeSpecificErrorNumber then
  'Some specific error occurred, circumvent the problem somehow
  Problem Circumvented Somehow...

  'Now that we took some alternative approach, we want to clear the
  'Err object
  Err.Clear        'Cleared the error... continue on with the script
End If

The Raise method generates a runtime error, and has the following definition:

Err.Raise 
                  Number, Source, Description, HelpFile, HelpContext

When developing reusable scripts, often the developer who writes a given reusable script is not the only one who uses it in practice. For example, in Chapter 5, we will look at how to create a reusable server-side form-validation script. While I wrote the code and use it, I don’t expect to be the only developer who will use it. The server-side form-validation script presented in Chapter 5 expects certain inputs from the developer using the script. If these inputs are out of acceptable ranges, an error is raised so the developer is notified immediately when trying to execute the script.

When raising errors in your own objects, Microsoft suggests that you add the VBScript constant vbObjectError to the custom error code. Examples in this book using the Raise method add vbObjectError to the error number, like so:

Err.Raise vbObjectError + ErrorNumber, ...

Tip

There is nothing magical about vbObjectError . It is simply a constant with a value of 80040000 hexadecimal.

Since this book focuses on building reusable, robust scripts, throughout this book we’ll use the Raise method of the Err object extensively.

Deciding when to check if an exception occurred

Virtually any line of code can cause an exception. A given exception is either consistent or inconsistent. A consistent exception is one that occurs every time the script is executed. For example, the following line of code is an example of a consistent exception:

Dim 4GuysFromRolla         'variable names cannot begin with a number

This exception is consistent, since every single time an ASP page is visited with the above line of code, an error will be generated. The following lines of code demonstrate an inconsistent exception:

'Connect to a database
Dim objConn
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.ConnectionString = "DRIVER={Microsoft Access Driver (*.mdb)};" & _
                           "DBQ=C:InetPubwwwrootdatastoresNWind.mdb;" & _
                           "UID=admin;PWD=;"
objConn.Open          'Open a connection to the database

An error would occur if the database file NWind.mdb did not exist in the path specified in the ConnectionString property (C:InetPubwwwrootdatastores). Such an exception is inconsistent because the above script would work flawlessly so long as the database was in the right directory. Imagine, though, that NWind.mdb was moved or renamed. Once that occurred, the script would start producing error messages when the Open method was reached.

Consistent exceptions are simple to detect. When testing a script that contains:

Dim 4GuysFromRolla

a developer can quickly diagnose and remedy the problem. Since inconsistent exceptions happen more unexpectedly, it is these exceptions that error detection should be employed for. After each line that may generate an inconsistent exception, be sure to place an If statement to check if Err.Number is not equal to zero. Those statements that might cause inconsistent exceptions are usually limited to methods of COM objects, such as the Open method of the ADO Connection object. Therefore, when using COM objects in your ASP scripts, be sure to check for errors immediately after calling one of the COM object methods.

In Section 3.3, we look at how to gracefully handle exceptions that occur using VBScript exception handling.

Error handling in functions and subroutines

If your ASP page contains any functions or subroutines, error handling becomes somewhat trickier. If you enable error handling at the start of your ASP page and then call a function or subroutine that contains a runtime error, the function or procedure will halt and pass control back through the call stack until a procedure with enabled error handling is found. Figure 3.1 illustrates this concept graphically.

When an error occurs in a non-error handling-enabled procedure, control is passed back through the call stack until a procedure with error handling enabled is found

Figure 3-1. When an error occurs in a non-error handling-enabled procedure, control is passed back through the call stack until a procedure with error handling enabled is found

When a function or subroutine is called, error handling is deactivated. Therefore, if you want a function or subroutine to be able to perform error handling on its own (that is, if you don’t want it to halt and pass control back to the calling procedure), you must explicitly turn on error handling in the function or subroutine with On Error Resume Next. Example 3.2 examines VBScript’s error-handling conventions with functions and subroutines.

Example 3-2. When an Error Occurs in a Function or Subroutine, Control Is Passed Up the Call Stack Until an Error-Handling Enabled Function or Subroutine Is Found

<% @LANGUAGE="VBSCRIPT" %>
<% Option Explicit %>

<%
  'Enable error handling
  On Error Resume Next

  'Call Procedure1
  Procedure1

  'We can check to see if an error occurred
  If Err.Number <> 0 then
    Response.Write "An error occurred!<BR>"
    Response.Write Err.Number & " - " & Err.Description
  End If

  Sub Procedure1(  )
    'No error handling here
    'Call Procedure2
    Procedure2
  End Sub


  Sub Procedure2(  )
    'No error handling here either

    'Whoops, an error occurred!  (Using an undeclared variable)
    strScott = strMitchell

    'The above error will halt Procedure2, returning control to Procedure1. Since 
     there is no error handling implemented there, ontrol is returned to the'line 
    'immediately following the call 'to Procedure1.  Since error handling is enabled
    'there, it will handle the error. (Otherwise, the user would be shown
    'an error message.)
  End Sub
%>

Note that the error-handling code after the call to Procedure1 is tripped for the error that occurred in Procedure2. The output of the code in Example 3.2 is as expected:

An error occurred!
500 - Variable is undefined

Streamlining VBScript error-handling code

With VBScript error handling, after each statement that might cause an exception, the developer needs to determine whether an error occurred. The following code is usually found after every potential error-causing statement:

If Err.Number <> 0 then
  Display an error message
End If

This approach can be streamlined a bit by using a subroutine to determine if an error has occurred or not. This subroutine, CheckForError, should have the following definition:

Sub CheckForError(strErrorMessage)

strErrorMessage is a string containing the error message that should be displayed to the user if an error occurs. After each line of code that may cause an error, the clunky:

If Err.Number <> 0 then
  Display an error message
End If

can be replaced with:

CheckForError strErrorMessage

The CheckForError subroutine contains fairly straightforward code, simply checking to see if Err.Number is nonzero. If it is, strErrorMessage is displayed and execution is halted with Response.End. Example 3.3 contains the source code for CheckForError.

Example 3-3. The CheckForError Subroutine Allows for More Streamlined Error-Handling Code in VBScript

Sub CheckForError(strErrorMessage)
  If Err.Number <> 0 then
    'An error occurred!  Display the error message
    Response.Write strErrorMessage
    Response.End
  End If
End Sub

Unfortunately, this subroutine needs to exist in all of your ASP pages that use scripting-language error handling. Of course, server-side includes should be used so that only one instance of this function is needed. Later in Section 3.3, we look at how to improve this subroutine to include the ability to notify the support team of the exception’s details.

Tip

A list of VBScript runtime error numbers can be found on Microsoft’s scripting site at: http://msdn.microsoft.com/scripting/default.htm?/scripting/vbscript/doc/vsmscRunTimeErrors.htm. VBScript syntax error numbers are listed at: http://msdn.microsoft.com/scripting/default.htm?/scripting/vbscript/doc/vsmscSyntaxErrors.htm.

Detecting errors with JScript

JScript’s error handling is similar to C++’s and Java’s, using try ... catch blocks. Error handling is fairly new to JScript; it’s only available in the JScript scripting engine Version 5.0 or greater. To download the free, latest version of the JScript and VBScript scripting engines, direct your browser to http://msdn.microsoft.com/scripting.

Tip

If you have IIS 5.0 installed as your web server, the Version 5.0 scripting engines are already installed on your computer. If you are using IIS 4.0, you may have an older scripting engine version, and should upgrade your scripting engine at Microsoft’s Scripting Site (http://msdn.microsoft.com/scripting ).

In VBScript, error handling is enabled with the On Error Resume Next command. If an exception is raised, the Err object is populated with the error information. To detect an error, after each line of code that may be guilty of causing an error, a test is performed, checking to see if Err.Number is nonzero. In Section 3.2.1.1,these actions were likened to an inefficient manager, continually checking on an employee to see if he had performed some erroneous task.

JScript’s error handling is a bit different. In JScript, there is no single command (like VBScript’s On Error Resume Next) that indicates that error handling should be enabled. Furthermore, JScript’s error handling takes a more direct approach than VBScript’s. To relate it to the manager/employee analogy used earlier, rather than asking our employee if an error occurred after he has attempted a task, we cautiously tell our employee to try a certain set of tasks. The employee then attempts to perform these tasks, and gets back to us if any of these tasks caused an error.

To let our dutiful employee know what tasks to perform, a try block is used, which has the following syntax:

                  try {
  possibly erroneous statements
}

A try block must be immediately followed by a catch block. A catch block contains code that is executed only if an error occurred in the commands within the preceding try block.

                  catch (errorObjectInstance) {
  error handling code
}

If an error occurs in one of the commands issued within a try block, the details of the error are encapsulated within an Error object. An instance of this object is assigned to the variable specified by errorObjectInstance immediately following the catch statement in the catch block.

The JScript Error object is similar to VBScript’s Err object, but only contains two properties and no methods. The two properties of the Error object can be seen in Table 3.2.

Table 3-2. The JScript Error Object Contains Two Properties

Property

Description

description

A string containing detailed information on the exception.

Number

A 32-bit number containing both a facility code and the actual error number. The upper 16 bits are the facility code, while the lower 16 bits are the error number.

The way Microsoft chose to represent their error numbers is, in my opinion, a little confusing. The easiest way to pick apart an error number is to look at it in hexadecimal format. All error codes you’ll receive through an ASP page will have the following hexadecimal format:

800FNNNN

The F denotes the facility code, which indicates who raised the error. VBScript and JScript use a facility code of 10 (A, in hex). The NNNN represents the actual error number. Therefore, using JScript’s number property, to get the NNNN portion of the 32-bit error number, use the following:

try {
  some code...
} catch (err) {
  // display the error number, less the 800F
                    Response.Write("The error generated the following error code: ");
  Response.Write(err.number & 0xFFFF);
}

Likewise, to obtain just the facility code, use the following:

try {
  some code...
} catch (err) {
  // display the error number, less the 800F
                    Response.Write("The error generated the following facility code: ");
  Response.Write(err.number >> 16 & 0xF);
}

Tip

A list of JScript runtime error numbers can be found on Microsoft’s scripting site at http://msdn.microsoft.com/scripting/default.htm?/scripting/jscript/doc/jsmscRunTimeErrors.htm. JScript syntax error numbers are listed at http://msdn.microsoft.com/scripting/default.htm?/scripting/jscript/doc/jsmscSyntaxErrors.htm.

The try block can contain several lines of code; as soon as an error occurs, the corresponding catch block is visited. Therefore, a separate set of try ... catch blocks should be used for each statement that might generate an exception. As discussed in Section 3.2.1.2, method calls to COM objects are the usual suspects for inconsistent exceptions; therefore, a try ... catch block should exist for each COM object method call.

Recall that VBScript’s Err object contains a Raise method, which, as its name implies, raises an error. JScript’s Error object does not contain any such method; to raise an error in JScript, use the throw statement. throw has the following syntax:

                  throw 
                  errorObjectInstance;

errorObjectInstance needs to be an Error object instance with its number and description properties already set. Example 3.4 demonstrates how to use the throw statement.

Example 3-4. The throw Statement Raises an Error

<% @LANGUAGE="JSCRIPT" %>
<%
  function ThrowError(  )
  {
    // throw an error...
    var err;
    err = new Error(  );       // Create an Error object instance
    err.description = "Egad, an error!";
    err.number = 0x800A1234;

    throw err;               // throw the error (similar to Err.Raise)
  }

  // try calling the function ThrowError
  try {
    ThrowError(  );
  } catch (err) {
    // If we've reached here, an error occurred.  Display the error info...
    Response.Write("An error occurred!  Here are the following details:");
    Response.Write("<P><UL>Description: " + err.description);
    Response.Write("<BR>Error Number:</B> " + (err.number & 0xFFFF));
    Response.Write("<BR>Facility Code:</B> " + (err.number >> 16 & 0xF));
  }
%>

Nested try ... catch blocks

try ... catch blocks can be nested within one another. For example, the following is perfectly legal syntax:

try {  // outer try block
  try {  // inner try block
    // something
  } catch (err) {
    // this catch block is only visited if an error occurs in the
    // code within the inner try block
  }
} catch (err) {
  // this catch block is only visited if an error occurs in the
  // code within the outer try block
}

While explicit try ... catch block nesting isn’t often used, implicit try ... catch blocks are quite common. Example 3.5 illustrates a pair of try ... catch blocks nested implicitly. The inner try ... catch block is within the function foobar ; the outer try ... catch block contains the code that calls foobar.

Example 3-5. try ... catch Blocks Can Be Implicitly Nested

function foobar(  )
{
  // this is the inner try ... catch block
  try {
    // execute some code that might throw an exception...
  } catch (err) {
    // handle an error
  }
}

// this is the outer try ... catch block
try {
  foobar(  );
} catch (err) {
  // handle any errors thrown by foobar(  )
}

In Example 3.5, the catch block in the outer try ... catch block will never be visited, since if any error occurs in foobar, the inner catch block will respond. There may be times, however, when the inner try ... catch block in foobar might not want to respond to an error. For example, when creating reusable scripts using JScript, there may be instances when you don’t want your reusable script to be responsible for handling all possible errors. In Chapter 6, we’ll examine a reusable script that creates generic database administration pages. These scripts work tightly with a database that is specified by the end developer (that is, the developer who is utilizing these reusable scripts). If the end developer specifies a database connection string that is invalid, it might be best to let the end developer handle the error rather than attempting to have the reusable script do so. The end developer might want to try a different connection string, perhaps, and if passed the error, might be able to recover from it.

To hand off the responsibility of handling an error, simply re-throw the error in the catch block. In the following code snippet, the catch block is only interested in working with a specific error, 0x800A1234; all other errors are passed on:

try {
  some code that might throw an exception
} catch (err) {
  // only handle error 0x800A1234
  if (err.number == 0x800A1234) {
    handle the error
  } else {
    // pass off the responsibility to the outer try ... catch block
    throw err;
  }
}

Example 3.6 demonstrates how the responsibility of handling an error can be passed from an inner try ... catch block to an outer one.

Example 3-6. To Pass Off the Responsibility of Handling an Exception from an Inner to an Outer try ... catch Block, Re-throw the Exception

<% @LANGUAGE="JSCRIPT" %>
<%
  function foobar(  )
  {
    // foobar tries to connect to a database.  If it cannot because of an
    // an invalid data source name, the catch block re-throws the error, passing
    // off the responsibility to the outer catch block...
    try {
      // attempt to connect to the database...
      var objConn;
      objConn = Server.CreateObject("ADODB.Connection");
      objConn.ConnectionString = "DSN=NonExistentDSN";
      objConn.Open(  );
    } catch(err) {
      if ((err.number & 0xFFFF) == 16389)
        throw err;                      // pass off the responsibility
      else {
        // not a connection problem... handle the error
      }
    }
  }

  // try calling the function ThrowError

  try {
    // Execute foobar; if there is a problem, the catch block will be visited
    foobar(  );
  } catch (err) {
    // at this point, we could check to see if the DSN name was bad, and, if
    // so, retry foobar or call some other function

    // Instead, for this example, we'll just output the error information
    Response.Write("An error occurred!  Here are the following details:");
    Response.Write("<P><UL><B>Description:</B> " + err.description);
    Response.Write("<BR>Error Number:</B> " + (err.number & 0xFFFF));
    Response.Write("<BR>Facility Code:</B> " + (err.number >> 16 & 0xF));
  }
%>

VBScript’s error handling versus JScript’s error handling

Now that we’ve examined both VBScript and JScript’s error-handling mechanisms, which one is best? I find JScript’s implementation of error handling to be much more elegant and readable than VBScript’s. Since VBScript’s error-handling approach requires the developer to inquire whether an exception occurred or not after the fact, the approach is more error-prone that JScript’s, where the developer must set up the proper error-handling calls prior to executing the questionable statements.

I also find the JScript syntax far more elegant than VBScript’s error-handling syntax. Of course, to enjoy the benefits of JScript error handling, you do have to use JScript as the server-side scripting language, something only a handful of ASP developers do.

Detecting Exceptions with the ASPError Object

As veteran web surfers, we’ve all stumbled across a broken link, which took us to a nonexistent web page. When clicking on a broken link, an HTTP 404 error is received. This error is generated by the web server when it cannot find a requested document.

Whenever something goes awry deep within a web server, an HTTP error is generated. These HTTP errors are three digits in length, ranging from 100 -505. The first number in the three-number HTTP error code denotes the type of HTTP error. 400-level errors are client errors, such as 404 (file not found), 401 (unauthorized), and 414 (request URL too long). 500-level errors indicate intrinsic web server errors. As we’ll see shortly, IIS 5.0 uses a 500-level HTTP error to signal that an error has occurred on an ASP page.

Tip

A complete listing of HTTP error codes and their associated meanings can be seen at http://www.webpartner.com/html/AlertsandErrors.htm.

Prior to ASP 3.0, exception handling on an ASP page was limited to the exception-handling capabilities of the scripting language used. Due to the total lack of error handling in JScript (until Version 5.0) and the verbose nature of error handling in VBScript, ASP was long overdue for a simpler and more effective exception-handling approach. With the release of ASP 3.0 (available exclusively with IIS 5.0 and Windows 2000), a new intrinsic object, ASPError, was added to assist in exception handling. The ASPError object contains nine properties, which are detailed in Table 3.3.

Table 3-3. The Intrinsic ASPError Object Assists in Detecting and Handling Exceptions

Property

Description

ASPCode

Returns a rather detailed error code that is generated by IIS

Number

Returns the error number

Source

Returns the line of code that caused the error, if available

Category

Indicates what type of error occurred; this property will indicate if the exception was caused by the scripting language, an external COM component, or an internal ASP error

File

Returns the name of the ASP page that generated the error

Line

Returns the line number the error occurred on

Column

Returns the column the error occurred on

Description

Returns a detailed description of the error

ASPDescription

Returns a detailed description for those errors that fall under the internal Active Server Pages error Category

When an error occurs in IIS 5.0, whether it’s from a COM object, the scripting language, or an internal ASP error, an HTTP 500;100 error is generated. (The 100 indicates that it is a special kind of HTTP 500 error.) Whenever an HTTP error occurs, IIS checks an error table to see what it should do in response to the error. Its choices are limited to:

  • Sending a default message to the client

  • Sending the client the contents of a particular file (usually an HTML file)

  • Redirecting the client to an error-handling web page

Through the Internet Information Services, a developer can specify how IIS should handle particular HTTP errors. Start by opening the Internet Information Services (in Windows 2000, go to Start Programs Administrative Tools Internet Services Manager). Right-click on the web site whose HTTP errors you wish to modify and choose Properties. The Web Site Properties dialog box will open; the HTTP error-handling information is under the Custom Errors tab. Figure 3.2 shows a listing of these HTTP errors for IIS on my Windows 2000 machine.

The Custom Errors tab in the Web Site Properties dialog box specifies how IIS responds to various HTTP errors

Figure 3-2. The Custom Errors tab in the Web Site Properties dialog box specifies how IIS responds to various HTTP errors

Notice that in Figure 3.2 the 500;100 HTTP error redirects the user to the URL /CODEREUSE/Error.asp. To adjust your settings for this HTTP error, select the particular error and click the Edit Properties button. You should now be presented with the Error Mapping Properties dialog box that contains a list box and a text box. The list box contains the three various options IIS can take when an HTTP error occurs: send the default message to the client (Default), send the client a file (File), or redirect the client to a URL (URL). Figure 3.3 contains a screenshot of the Error Mapping Properties dialog box for the HTTP 500;100 error.

The Error Mapping Properties dialog defines how IIS handles particular server errors

Figure 3-3. The Error Mapping Properties dialog defines how IIS handles particular server errors

With the settings shown in Figure 3.3, whenever an internal web server error occurs in an ASP page, the HTTP 500;100 error will be tripped. This will send the user to /CODEREUSE/Error.asp via an implicit Server.Transfer. Figure 3.4 graphically depicts this branch in execution.

When an error occurs on an ASP page, an HTTP 500;100 error is generated, branching execution to /CODEREUSE/Error.asp

Figure 3-4. When an error occurs on an ASP page, an HTTP 500;100 error is generated, branching execution to /CODEREUSE/Error.asp

When an error occurs on an ASP page, not only is a HTTP 500;100 error generated, but the details of the error are packaged into an ASPError object instance. This particular ASPError object instance can be retrieved in the error-handling web page using the GetLastError method of the Server object. Example 3.7 contains the source code for our error-handling web page, /CODEREUSE/Error.asp.

Example 3-7. The Error-Handling Web Page Obtains Error Information Using Server.GetLastError

<% @LANGUAGE = "VBSCRIPT" %>
<% Option Explicit %>
<%
  'Grab the instance of the ASPError object that contains info on
  'the error that brought us to this error-handling web page
  Dim objError
  Set objError = Server.GetLastError(  )
%>

<FONT SIZE=+1><B>D'oh!</B></FONT><HR NOSHADE>
An unexpected error occurred.  We apologize for this inconvenience.
<P>
<!-- Display Error Information -->
<TABLE ALIGN=CENTER BORDER=1 CELLSPACING=1>
<TR><TH COLSPAN=2>Detailed Error Information</TH></TR>
<TR>
  <TH>Property</TH>
  <TH>Value</TH>
</TR>
<TR>
  <TD>ASPCode</TD>
  <TD><%=objError.ASPCode%></TD>
</TR>
<TR>
  <TD>Number</TD>
  <TD><%=objError.Number%></TD>
</TR>
<TR>
  <TD>Source</TD>
  <TD><%=objError.Source%></TD>
</TR>
<TR>
  <TD>Category</TD>
  <TD><%=objError.Category%></TD>
</TR>
<TR>
  <TD>File</TD>
  <TD><%=objError.File%></TD>
</TR>
<TR>
  <TD>Line</TD>
  <TD><%=objError.Line%></TD>
</TR>
<TR>
  <TD>Column</TD>
  <TD><%=objError.Column%></TD>
</TR>
<TR>
  <TD>Description</TD>
  <TD><%=objError.Description%></TD>
</TR>
<TR>
  <TD>ASPDescription</TD>
  <TD><%=objError.ASPDescription%></TD>
</TR>
</TABLE>
<%
  Set objError = Nothing         'Clean up...
%>

The error-handling code in Example 3.7 uses the Server.GetLastError method to obtain information on the error that caused the HTTP 500;100 error. Next, the properties of the ASPError object are displayed in an HTML table. As we discussed earlier, the end user shouldn’t be bothered with the technical details of the error, and usually we wouldn’t want to display this detailed information.

As illustrated in Table 3.3, one of the ASPError object’s properties is Category, which indicates which one of three categories the error falls under. The three possible error categories are:

  • Scripting language error

  • Internal ASP error

  • External COM error

For the remainder of this section, we will examine code snippets that generate an error in a unique category. After each code snippet, we’ll examine the output generated by the error-handling script in Example 3.7.

Scripting language errors

A scripting language error occurs when code that violates the scripting language’s syntax is encountered. For example, in VBScript an If statement has the following syntax:

If condition then
  Statements
[ElseIf condition then
  ElseIf statements]
[Else
  Else statements]
End If

Or

If condition then Statements [Else Else Statements]

Writing an If statement that violates this expected syntax will result in a scripting language error. Example 3.8 contains the source code to ScriptingLanguageError.asp, which is a script with an illegal If statement. When ScriptingLanguageError.asp is visited through a browser, the user is automatically redirected to /CODEREUSE/Error.asp. A screenshot of a browser visiting ScriptingLanguageError.asp can be seen in Figure 3.5.

Example 3-8. A C-Style If Statement Generates a Scripting Language Error When Using VBScript

<% @LANGUAGE="VBSCRIPT" %>
<% Option Explicit %>
<%
  if (1 = 2)
    Response.Write "What!?  1 = 2?"
%>
A scripting language error produces these values in the ASPError object’s properties

Figure 3-5. A scripting language error produces these values in the ASPError object’s properties

Detecting compile-time errors with the ASPError object

Unlike the scripting language error-handling methods, the ASPError object can be used to detect compile-time errors. This is evident from the code in Example 3.8, which generates a compile-time error. Note that, according to the Category property value listed in Figure 3.5, an improperly formatted If statement results in a “Microsoft VBScript compilation” error. This makes sense, since illegal syntax generates compile-time errors.

Internal ASP errors

When creating ASP pages, there are certain guidelines that must be followed regardless of the scripting language used. For example, server-side includes must have a certain syntax and must reference an existing file; when using the <% and %> script delimiters, these delimiters must match (that is, for every <% there must be a corresponding %>).

Internal ASP errors are a lower level of errors than scripting language errors. Scripting language errors are dependent upon the syntax of the particular scripting language used. On the other hand, internal ASP errors are scripting language-independent. When an internal ASP error occurs, the ASPDescription property of the ASPError object contains extra information further describing the error.

Example 3.9 contains the source code to InternalASPError.asp, a script that tries to include a file that does not exist. Figure 3.6 contains the output of the script when viewed through a browser. Note that the ASPDescription property contains information that was not present in the scripting language error case (Figure 3.5).

Example 3-9. Using a Server-Side Include to Import the Contents of a Nonexistent File Generates an Internal ASP Error

<% @LANGUAGE="VBSCRIPT" %>
<% Option Explicit %>
<%
  'An internal ASP error will be generated since we are attempting to include
  'a nonexistent ASP page...
%>
<!--#include file="NonExistentPage.asp"-->
An internal ASP error produces these values in the ASPError object’s properties

Figure 3-6. An internal ASP error produces these values in the ASPError object’s properties

External COM object errors

One of the reasons ASP is such a powerful tool for creating dynamic web pages is its ability to utilize COM components. COM components, like ADO objects, may raise errors if used improperly, or if an external exception is encountered. If such an error occurs in a COM component, the ASPError object classifies it as an external COM object error. The Category property is set to the programmatic identifier of the offending COM component.

Example 3.10 contains the source code for COMError.asp, a script that raises an external COM object error due to the fact that it attempts to close an ADO Connection object before it has been opened. The output of COMError.asp, when visited through a browser, can be seen in Figure 3.7.

Example 3-10. Attempting to Close a Closed Connection Object Results in an External COM Object Error

<% @LANGUAGE="VBSCRIPT" %>
<% Option Explicit %>
<%
  'The following code snippet will generate a COM object error, since we
  'can't close a database connection if it's already closed!

  Dim objConn
  Set objConn = Server.CreateObject("ADODB.Connection")
  objConn.Close
%>
An external COM object error produces these values in the ASPError object’s properties

Figure 3-7. An external COM object error produces these values in the ASPError object’s properties

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.193.158