There are oodles of pages out on teh intarwebs that will tell you how to set up custom error handling for your ASP.NET site. If that's what you're looking for, this post isn't for you. However, if you're looking to see how to take complete control over what your custom error pages do, and how they report back to clients, then read on.
404s with all the Guts and Glory
One great approach is to wire up error handling logic in your Global.asax's Application_Error event. I took this approach and was able to get it to work flawlessly with some 'spoofed' 404s that I recently created on one of my sites (i.e., I'm using tons of url-rewriting and needed to be able to discern when a path looked correct (had the right format), but didn't actually map to something in the Database or on the site - so throwing my own NotFoundExceptions was a great way to redirect to my own custom 404 page).
When I tried this same approach with actual 'errors' though I ran into a massive problem. My root problem in this case is that when I really encounter an exception, I want the HTTP STATUS CODE for the page in question to be a 500. If you use the customErrors configuration in the web.config, that works out as an HTTP 302, and if you're just doing Server.Transfer("myCustom500Page.aspx") from you Global.asax, you end up writing an HTTP 200 - which isn't something you want a robot to encounter when the page is obviously broken.
With my custom 404Handler.aspx page I was able to parse info about the exception being thrown to dynamically generate a helpful HTML page, and then spit out a 404. This was perfect - as it let me handle stupid user errors, as well as potential 'real' problems on the site with some decent markup on a custom error page without sending out an HTTP 200 which will cause the page to be indexed by robots should they happen upon it somehow.
What's Good for the Goose doesn't work for the Gander
But if you try the same thing with a custom error page (by doing Response.StatusCode = 500;) you run into a massive problem. What happens first is that it appears that ASP.NET sees the 500 error, assumes that something is wrong, and will attempt to redirect to your custom 500 page specified in the customErrors section of your web.config. (I'll spare you the story of the joy I had watching my site go into an infinite loop on those requests.)
But even worse than that is that once ASP.NET sees the ResponseCode get set to 500, it will try to hand off processing to the custom error page used by IIS. The pisser is that you can't get around this. I tried ApplicationInstance.CompleteRequest() immediately after setting Response.StatusCode = 500 - but that didn't do it. Neither did trying to override or piggy-back on to my custom error page's OnError (because, obviously, no error is being encountered - though the status code is being set to 500).
ASP.NET 3.5 and IIS7 to the Rescue
Just as I was starting to contemplate stuffing the Exception from Server.GetLastError() into Context.Items[], and then pulling it out in my custom errors page, I thought I'd take a peek at Response in IntelliSense to make sure I wasn't missing anything.
Sure enough, there's a new property that INSTANTLY caught my attention: Response.TrySkipIisCustomErrors. It's brand-new, and only works on IIS7 with ASP.NET 3.5. That, however, happened to be the exact platform that I'm on.
More importantly, it lets me:
a) Capture unhandled exceptions in my Global.asax's Application_Error Event Handler
b) Capture the exact error/exception with Server.GetLastError() (note that you'll want to grab that Exception's .InnerException if the Type is of Type HttpUnhandledException)
c) Programatically let me determine which error page to route to in order to handle the exception (depending upon type/details/etc)
d) Do more processing in the page that handles the error (such as enabling/disabling various error descriptions/panels/etc.)
e) Throw an HTTP 500 (or whatever) without getting my response-stream hijacked by IIS.
In other words, this gives me the best of everything: intelligent and dynamically generated custom error pages, and HTTP response codes that give me the control over robots/indexing that I need.
Thank you.
Posted by: Andreas Brekken | May 08, 2008 at 08:57 AM
This saved me. :D
Posted by: Mark Boughter | January 25, 2011 at 01:11 AM