Experience Sitecore! | All posts tagged '404'

Experience Sitecore!

Martin Miles on Sitecore

Handling 404 in Helix

When creating websites with Sitecore it is always nice to a have a nice and shiny 404-page that complies with the website styles and is content editable. Which will not work in all the cases, unfortunately. If the request falls out of site context - user won't get that nice and shiny page. So let's see what we can do in Helix, as it assumes multisite by design. The code below is written on top of Habitat, but that should not make a big difference.

Since this functionality is website agnostic and relates to Project layer, we will be using Project.Common.Website. Here is the  configuration within Common.Website.config:

<httpRequestBegin>
   <processor patch:before="processor[@type='Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel']"
    type="Sitecore.Common.Website.Pipelines.HandleRequestError, Sitecore.Common.Website"
    patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" />
</httpRequestBegin>

And the processor HandleRequestError.cs:

public class HandleRequestError : HttpRequestProcessor
{
    public override void Process(HttpRequestArgs args)
    {
        if (Context.Item != null || Context.Site == null)
        {
            return;
        }

        string filePath = HttpContext.Current.Server.MapPath(args.Url.FilePath);

        if (IsValidItem() 
             || ReservedUrls.Includes(args.Url.FilePath) 
             || File.Exists(filePath)) 
        {
            return;
        }

        if (Context.Database != null)
        {
            // if we are in a context of a specific site - serve content-editable 404
            Context.Item = Context.Database.GetItem(Context.Site.StartPath + "/404");
        }

        // return 404 HTTP status code in either cases, to be picked up further ahead
        HttpContext.Current.Response.TrySkipIisCustomErrors = true;
        HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotFound;
    }

    private bool IsValidItem()
    {
        if (Context.Item == null || Context.Item.Versions.Count == 0) return false;

        if (Context.Item.Visualization.Layout == null) return false;

        return true;
    }
}
So briefly, if we have website resolved - we serve its customized content-editable /404 page item (each of the sites has this page under the same root-relative path).