|Number of votes:||3|
One of the first task on my brand new path in EPiServer world was to develop custom error pages. Nothing special and no big deal at looking at the task from 10k feat.
We decided to take a Http module path – to plug in our module in request processing pipeline to inspect the situation on the server and make all the stuff needed to render the error page for appropriate HTTP status code.
Enabling custom error handler is as easy as adding following lines to your web.config file:
The first trick was about Http module and HttpApplication Error event. This event is raised only when there is a unhandled exception on the server by the Asp.Net runtime. The trick is to get back to the server processing pipeline even end-user requested resource that is not really associated with Asp.Net (for instance, user is requesting http://<server>/<app>/documenthatdoesnotexist.doc).
What we can do about this is to instruct IIS to execute some .aspx file for 404 Http status code. Trick here is that this file should not exist on the server therefore our module will be called and application will raise error blaming that our provided IIS 404 error displaying page does not exist.
By calling HttpContext.Current.Server.GetLastError().GetBaseException() we can get back to the original error occurred in “previous” request. I quoted “previous” request because request has not been completed and response is not served yet (because of Http error “ExecuteURL” mode).
If there are some issues with IIS and custom error pages (usually issue is that IIS is not allow use custom error pages) look at feature delegation configuration item in IIS server root. Search for “Error pages” and verify that it’s set to “Read/Write”.
After we get back on track we can investigate an exception occurred previously and make assumption on what status code to set for the response and which page to render.
Of course before rendering error page some checks should be made: for detecting infinite loops, request for some well known resources, etc.
So what the module is doing actually later when decision on which page to render is made? Module has following logic:
Lastly if the EPiServer kind page was found (step 1. or 2.) Trick was to render it correctly.
We ended with the following implementation:
More info in insights of Server.TransferRequest() and alternatives can be found here. We figured out that Server.Execute() does not work very well for 500 status pages. And somehow EPiServer is loosing preferred UI culture/language if method to render page is other than Response.Redirect(). Looking at EPiServer.PageBase class InitializeCulture() method suspicious line seemed to be:
Haven’t so much time to investigate all this.
Module as NuGet package is available at – nuget.episerver.com. Id: Geta.ErrorHandler.
Package also contains:
It uses log4net as internal logging transport according to EPiServer approach.
What it currently does not support is:
Hope this helps!