Handling Runtime Errors Globally
Unhandled runtime errors hit the best of us. But if you catch them at the Page and Application levels, you'll save yourself a lot of grief.
This column isn't for you; your applications don't have runtime errors. But you have a friend who gets errors. And this column is for him.
You should put Try...Catch blocks around any piece of code in your application that might fail. But you if you put all of your code around in Try...Catch blocks, you lose the ability to signal which sections of your code are likely to generate errors. This means that you'll have some sections outside of Try...Catch block that can have "unhandled" errors.
However, even so-called "unhandled" errors are handled because when an error occurs, the exception that's generated bubbles up through the call tree until it arrives at the default ASP.NET error handler. When the errors get to the ASP.NET error handler, your application is terminated, the white and tan error screen all developers are familiar with is displayed, and there's nothing more you can do in your code.
You can prevent exceptions from getting to the default handler -- and stay in control -- by catching "unhandled" errors at the Page and at the Application level.
Page Level Error Handlers
When an unhandled error occurs in a page (or in any code called from the page), the Page's Error event is fired. In that event you'll typically want to figure out what's gone wrong. Your best resource for that is the Server object's GetLastError method; it hands back the Exception object for the last error that occurred in the page:
Protected Sub Page_Error(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Error
Dim ex As Exception
ex = Me.Server.GetLastError()
However, just because you've caught the error, that doesn't mean that the error has finished its travels. By default, the error will continue to bubble up the call tree until it reaches the default ASP.NET error handler and terminates your application. To prevent the error from continuing its trip up the tree, you must call the Server object's ClearError method:
The pattern in the Page Error handler is very simple. Therefore:
- Try to determine what the error was.
- Try to determine what you can do about it.
- If you can deal with the error, clear the error.
- If you can't deal with the error in the page, do nothing and let the error continue to bubble up the tree.
Application-Level Error Handlers
If you can't deal with the error, you should probably write the error to an error log of some kind (some day you can review that log, figure out what's going wrong and fix it) and direct the user to your own error page. If, regardless of which page has the error, you're always going to write to the same error log and send users to the same error page, then you should do that at the application level, not the page level.
To catch unhandled errors not cleared at the application level, you need to add code to the Application_Error event in your application's Global.asax file. In ASP.NET you don't get a Global.asax file by default so you'll have to add that file (in the Add New Item dialog, it's called the Global Application Class).
As in the Page Error event, you'll want to retrieve the latest exception but you don't need to clear the error (at least in ASP.NET 2.0 and later). Once you have the exception you can write to your error log and, after that, direct the user to your site's error page. A typical routine looks like this:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim ex As Exception
ex = Server.GetLastError
You, of course, never have unhandled runtime errors in your code. But I'm sure that your "friends" will appreciate it if you share this information with them.
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.