[thelist] Friday Freebie

Scott Dexter sgd at ti3.com
Fri Feb 2 13:34:37 CST 2001


<tip type="ASP" subject="Nice Error Handling" author="sgd"
email="sgd at thinksafely.org">

Well, you got your site up and its running great. You had the launch party,
and today's biggest task is hanging around the office long enough for the
hangover to subside.

And then you get an email. Someone --a user-- got this cryptic error page
that says eight-zero-zero-something-er-other. She's not too happy, and
completely confused as to what to do.

ick. Forget that there's a run-time error that sneaked through your
exhaustive testing. What a way to greet a user if --god forbid-- they cause
an error. What to do? 

You can give them generic text by changing the application settings for the
site properties in the MMC, but this doesn't do you any good if you actually
want to be notified of the error. Using <% On Error Resume Next %> all over
the place isn't that complete either, because if an error does happen, who
knows what kind of la-la land your app will go into if you don't trap it and
take action.

Okay, so here's what we do: We use <% On Error Resume Next %> and test the
Err object like crazy (like after *every* database access, for example).
Using some techniques we've already seen
(http://evolt.org/article/Using_files_to_send_emails_with_IIS_part_1_of_2/17
/3419/index.html) or your own email routine(s), we even send ourselves an
email telling us something went wrong, and where, because we like being
proactive. Then we give the user a nice page so they don't freak. =)

So how do we check the Err object like crazy? We wrap a few lines inside a
function and call the function (you didn't think you were going to cut-paste
8 lines of code everywhere, did you? C'mon, that's just nnnnnnnuts)--

<%
Function CheckErr(byref oErr, byval context)
if (oErr) then
	' do your special magic in here
	subject = "Error found on page " &
Request.ServerVariables("SCRIPT_NAME")
	mailto = "sgd at thinksafely.org"
	mailfrom = "ErrorHandler at myweb.com"
	body = oErr.Number,Request.ServerVariables("SCRIPT_NAME")&": "&
context & ": "& oErr.Source & ": "& oErr.Description
	SendEmail mailto, mailfrom, subject, body
	oErr.Clear
	Session.Abandon
	Response.Redirect "asperror.htm"
end if
End Function
%>

Let's take a look at a couple things.

I pass the Err object by reference. This is on purpose, because I want the
same Err object that could contain the error information. If I pass it by
value, I may not get the error (this was verified through testing). There's
also the "context" parameter. When you turn off the intrinsic error
trapping, you lose some information, namely the filename and line number the
error occurred on. The Err object in IIS5 is better, but the IIS4 Err object
doesn't provide everything, so we have a parameter to fill in what the hell
we were doing when the error popped up and bit us. I usually stick in the
sql string I was working with at the time of the call.

We can get away with the simple <% IF (oErr) %> statement because the
default property of the Err object is Err.number, which is non-zero if
something happened.

The SendMail() function would be your homework assignment. The link above
outlines one way to send out emails, but I'm sure you have a tried-and-true
method already in place, so go ahead and use that. Notice I use the HTTP
server variable "SCRIPT_NAME" --this is the virtual path to the page that
caused the error (since the Err object doesn't contain it). Basically, we
just pump the email full of the error information and send it off.

To clean up, I abandon the Session and redirect to a generic "an error
occurred please try again later" page. This is because in most of my apps if
a run-time error occurs, its bad enough to throw everything on the floor and
make them start over. This is where the user sees a nice page and you
display what you want them to see. Hell, with a few lines, you could pass
along the error and context information to that page, and make it very
informative *and* nice. How fucking professional can we get? ;)

At the very least, we make sure we don't pass the same error along to the
next CheckErr() call by doing the oErr.Clear method. This resets the Err
object.

To use this routine, we need to sprinkle some code in important places in
the app, like so:

<%
' turn off intrinsic error trapping
On Error Resume Next

' do something potentially dangerous here
Set oRS = oConn.Execute(nefariousSQLString)

' Check the Err object AS SOON AS POSSIBLE!
CheckErr Err, "trying: " & nefariousSQLString

' turn built in Error checking back on
On Error Goto 0
%>

Bonus: ASP.NET has a Try-Catch-Finally control structure that is much, much
cleaner to use when you're wanting to trap errors. But we'll hafta wait for
that....

</tip>

sgd
--
work: http://www.ti3.com/
non: http://thinksafely.org/




More information about the thelist mailing list