Blog about tips & tricks for CMS enhancement

eric.petersson

Create a custom 404 page in Episerver with BVN.404Handler


The problem

Quite often you are in need of customizing a 404 page for your customer's need of viewing a proper not found-page. Most likely, the customer also wants the ability to dynamically change the view of this custom page.

In this post, we will create a custom 404 page directly beneath the Episerver start page in the site tree and make the page editable for the editors.

The solution

Luckily, Geta has made a very fine hands on Nuget-extension for this specific task: BVN.404Handler. With this extension installed you may set up an action controller to handle the not found request by making a custom attribute:

CustomPageNotFoundAttribute.cs

using BVNetwork.NotFound.Core.NotFoundPage;
using EPiServer.Editor;
using System.Web.Mvc;
 
namespace ProjectNamespace
{
    public class CustomPageNotFoundAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (PageEditing.PageIsInEditMode)
            {
                return;
            }
 
            var request = filterContext.HttpContext.Request;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
 
            var statusCode = NotFoundPageUtil.GetStatusCode(request);
            filterContext.HttpContext.Response.StatusCode = statusCode;
 
            var status = NotFoundPageUtil.GetStatus(statusCode);
 
            if (!string.IsNullOrEmpty(status))
            {
                filterContext.HttpContext.Response.Status = status;
            }
 
            NotFoundPageUtil.SetCurrentLanguage(filterContext.HttpContext);
 
            filterContext.Controller.ViewBag.Referrer = NotFoundPageUtil.GetReferer(request);
            filterContext.Controller.ViewBag.NotFoundUrl = NotFoundPageUtil.GetUrlNotFound(request);
            filterContext.Controller.ViewBag.StatusCode = statusCode;
            
            filterContext.Controller.ViewBag.BottomText = NotFoundPageUtil.Get404PageLanguageResourceContent().BottomText;
            filterContext.Controller.ViewBag.CameFrom = NotFoundPageUtil.Get404PageLanguageResourceContent().CameFrom;
            filterContext.Controller.ViewBag.LookingFor = NotFoundPageUtil.Get404PageLanguageResourceContent().LookingFor;
            filterContext.Controller.ViewBag.TopText = NotFoundPageUtil.Get404PageLanguageResourceContent().TopText;
            filterContext.Controller.ViewBag.Tilte = NotFoundPageUtil.Get404PageLanguageResourceContent().Title;
 
        }
 
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
 
        }
    }
}

As you can see, we will handle the request to listen for a not found call and guide the request further through the BVN404-extension.

We will decorate this action attribute on our controller class like the following:
ErrorPageController.cs

using EPiServer.Web.Mvc;
using System.Web.Mvc;

namespace YourProjectNamespace
{
    [CustomPageNotFound]
    public class ErrorPageController : PageController<ErrorPage>
    {
        public ActionResult Index(ErrorPage currentPage)
        {
            var model = new ErrorPageViewModel(currentPage);

            return View(model);
        }
    }
}

And lastly we will give our page a presentation by adding the built in BVN404 properties for displaying an example not found page. This will look something like this:

Index.cshtml

@model ErrorPageViewModel
 
<div id="error-page" class="container">
    <div class="row">
        <div class="col-md-12">
            Referrer: @ViewBag.Referrer
            NotFoundUrl: @ViewBag.NotFoundUrl
            StatusCode: @ViewBag.StatusCode
 
            BottomText: @Html.Raw(ViewBag.BottomText)
            CameFrom: @Html.Raw(ViewBag.CameFrom)
            LookingFor: @Html.Raw(ViewBag.LookingFor)
            Title: @ViewBag.Title
        </div>
    </div>
</div>

Make sure your web.config for customErrors or HttpErrors points to your created not found page type in the Episerver url segment. If your page lives directly beneath the start page and is called /404, give it the path syntax like the one below (my default master language is to Swedish):

web.config

<httpErrors errorMode="Custom" existingResponse="Replace">
      <remove statusCode="404" />
      <!--<error statusCode="404" path="/404" responseMode="ExecuteURL" />-->
      <!--<error statusCode="404" path="/en/404" responseMode="ExecuteURL" />-->
</httpErrors>

image

Hopefully this will resolve your needs for structuring a well implemented not found page in Episerver!