Making ASP.Net Custom Errors Less Dookie
I wanted to share some lessons learned from an experience recently adding custom error pages to one of our FubuMVCprojects deployed to IIS7.
Treat your users well
ASP.Net has this all handled right?
Sure they do. Well sort of. Lets take a look at your web.config.
httpErrors – good for static content
An httpError seems to allow you to customize error pages for static sites and the parts of your app that do not flow through the ASP.Net runtime. For us this worked well for our 404. The main problem here is that you cannot use a virtual path to your error page.
Unfortunately, this requires that we have a deployment step to set the correct value in the path attribute of the error element.
customErrors – almost good but not quite great
A customError tells ASP.Net to avoid the built in IIS (404, 403) and Yellow Screens of Death (500) error pages and instead use what you provide.
We ran into one major problem with this. What actually happens under the hood is that an error on your page generates a 302 redirect to your custom error page.
This doesn’t seem too bad. Until you think about it. You have an error page with is ultimately returning a 200 OK status. It is saying everything is OK when it is NOT. The mismatched status code breaks the semantic contract your error page has with your browser.
Where this goes terribly wrong is with AJAX requests. AJAX will now receive no error when things go wrong. This has the effect of really messing up AJAX requests that pull in server side generated views.
See how the error page is plopped into the middle of the website. Lovely. This happened because jQuery’s ajax method dutifully followed the error redirect pulled in the error page’s html content into results div.
We have error handlers which look much nicer. Let’s make them work.
Fixing the AJAX error redirect problem
We tried way to hard to get this to work. In the end it was something simple that our Dovetail colleagues had already found. The solution is to prevent the custom error page from rendering for AJAX requests. Turns out this is pretty easy.
This code is cancelling the error and rendering a short error page with the proper 500 error when something goes wrong. Now our example AJAX request can handle the error.
Hopefully this was useful and we didn’t miss too many obvious alternative solutions. Down the road I’d rather have a behavior in FubuMVC that skips the custom errors if they are enabled and also supports 403 authorization errors behind AJAX requests. Better yet I wish that custom errors would do the right thing and serve up the correct status by default.