Blog about tips & tricks for CMS enhancement

eric.petersson

Create a custom 500 internal server error page in Episerver


One recent request I received from a client was to address the default 500 internal server error page with a better design. Most of the times your visitors shouldn't end up on pages like these, but hence if they do we need to take care of it by making it look a bit more professional.

The code examples below reflects Episerver CMS 11.20.x - we will address this in MVC default patterns for taking control of the display of the status page. I found out that there was some minor tweeks needed to be involved in the Episerver framework section to make this work.

We will also not give the possibility to let editors or administrators of Episerver CMS management get the oppertunity to edit this page the way they want. We will end up displaying a static .cshtml file for the 500 internal server error. Pages like 404 not found is a more suitable approach to set the dynamic flow for editors.

First of start by adding a new route in your Global.asax.cs file for the MVC pattern to reflect the routing of the desired page to be displayed:

Global.asax.cs

protected override void RegisterRoutes(System.Web.Routing.RouteCollection routes)
{
    base.RegisterRoutes(routes);

    routes.MapRoute("InternalError", "InternalError", new { controller = "Default", action = "InternalError" });
}

After that we need to create the Controller in MVC to pipeline the give route. In the Controllers folder of your MVC project, create a controller called DefaultController:

DefaultController

using System.Net;
using System.Web.Mvc;
using System.Web.SessionState;

namespace MyProject.Controllers
{
    [SessionState(SessionStateBehavior.Disabled)]
    public class DefaultController : Controller
    {
        public ActionResult InternalError()
        {
            Response.TrySkipIisCustomErrors = true;
            Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            
            return View();
        }
    }
}

Here we decorate the MVC controller inheritage with SessionStateBehaviour.Disabled so that request is not handled as an action filter. We also say to skip IIS custom errors and set the Status code to 500 (InternalServerError).

In the Views folder of your MVC project, add a view under a folder named Default with a implementation of your own or something similiar to this:

Views/Default/InternalError.cshtml

<!DOCTYPE html>
<html>
<head>
    <title>An internal server error has occurred (status code 500)</title>
    <meta content="noindex, nofollow" name="ROBOTS" />
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">    
    <link href="https://fonts.googleapis.com/css?family=Merriweather:300|Source+Sans+Pro:300,300i,400,400i,600,700,700i" rel="stylesheet">
    <link href="style.css" type="text/css" rel="stylesheet" />
</head>
<body>
    <div class="page-content" role="main">
        <div class="empty-page">
            <div class="row">
                <div class="block sectionblock col-lg-12 col-md-12 col-sm-12 col-12">
                    <div class="bg bg-min-height pt-5 pb-5 bg-light">
                        <div class="container  align-self-center">
                            <div class="row row0 ">
                                <div class="block textbsblock col-lg-12 col-md-12 col-sm-12 col-12">
                                    <div class="text-center">
                                        <div class="rte">
                                            <h1>Status code 500</h1>
                                            <h2>An internal server error has occurred</h2>
                                            <p>We are sorry for this inconvenience and hope to be back soon enough.<br/>
                                            If the problem seems to be persistent, please use the contact button below and attach the url where this error occurred.</p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>      
    </div>
</body>

</html>

Make sure that the Episerver Framwork section in the web.config does NOT contain globalErrorHandling="off" or the attribute itself at all. That will tell Episerver to take control of the error handling pipeline:

web.config

<episerver xmlns="http://EPiServer.Configuration.EPiServerSection">
    <applicationSettings httpCacheability="Public" httpCacheExpiration="1:00:00" pageValidateTemplate="false" uiShowGlobalizationUserInterface="true"
      uiUrl="~/EPiServer/CMS/" urlRebaseKind="ToRootRelative" uiMaxVersions="10" uiEditorCssPaths="editor.css" strictLanguageRouting="false"/>
  </episerver>

Lastly, we also want in our web.config to get rid of the built in default status pages served from IIS by setting the httpError section to clear all presets before setting our custom build:

web.config

<httpErrors errorMode="Custom" existingResponse="Replace">
    <clear/>
    <error statusCode="500" path="/InternalError" responseMode="ExecuteURL"/>
</httpErrors>

There you go! You should be able to sabotage your solution on your own by messing up a connectionString to a database or someting similiar and see your custom 500 error page in action.

Code long and prosper!