Tag: 404

Sitecore: Returning a 404 response on the page requested rather than redirecting to a 404 page

Previously I've blogged about:

but while looking through the posts today, I realised I had never written about how you stop Sitecore from issuing 302 redirects to your 404 page and instead return a 404 on the URL requested with the contents of the 404 page.

While search engines will recognise a 302 response to a 404 as a 404 (in fact they're intelligent enough to work out that a 404 page without a correct response status code is a 404) it's considered SEO best practice for the URL to stay the same and to issue the correct status code.

Creating a NotFoundResolver class

When Sitecore processes a request it will run the httpRequestBegin pipeline, and within that pipeline is a Item Resolver processor that will attempt to find the requested item. If after this the context item is still null then the logic to redirect to the ItemNotFoundUrl will kick in. To stop this happening we can simply add our own process to the pipeline after ItemResolver and set the item.

Our class looks like this:

using Sitecore;
using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.HttpRequest;

namespace Pipelines.HttpRequest
{
  public class NotFoundResolver : HttpRequestProcessor
  {
      private static readonly string PageNotFoundID = Settings.GetSetting("PageNotFound");

      public override void Process(HttpRequestArgs args)
      {
          Assert.ArgumentNotNull(args, nameof(args));

          if ((Context.Item != null) || (Context.Database == null))
              return;

          if (args.Url.FilePath.StartsWith("/~/"))
              return;

          var notFoundPage = Context.Database.GetItem(new ID(PageNotFoundID));
          if (notFoundPage == null)
              return;

          args.ProcessorItem = notFoundPage;
          Context.Item = notFoundPage;
      }
  }
}

To add our process to the pipeline we can use a patch file like this:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
  <pipelines>
    <httpRequestBegin>
      <processor
        patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']"
        type="LabSitecore.Core.Pipelines.NotFoundResolver, LabSitecore.Core"  />
    </httpRequestBegin>
  </pipelines>
  <settings>
    <!-- Page Not Found Item Id -->
    <setting name="PageNotFound" value="ID OF YOUR 404 PAGE" />
  </settings>
</sitecore>
</configuration>

Notice the setting for the ID of your 404 page to be loaded as the content.

Remember if you do do this make sure you also follow one of the methods to return a 404 status code, otherwise you will have just made every URL a valid 200 response on your site.

Creating a custom 404 Page in Sitecore

Nobody wants to see the standard Sitecore 404 page. Thankfully it's really easy to change the error pages a user is redirected to through some config settings.

Your error pages can be pages in Sitecore or static HTML files. For 404 pages I would normally use a Sitecore page, that way content authors can still manage its content. For an Error Page I would recommend a static html file to avoid issues with the Error page potentially error-ing.

Add these to a patch file and update the urls accordingly:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
  <settings>
    <!--  ITEM NOT FOUND HANDLER
          Url of page handling 'Item not found' errors
    -->
    <setting name="ItemNotFoundUrl">
      <patch:attribute name="value">/ErrorPages/404.html</patch:attribute>
    </setting>
    <!--  LINK ITEM NOT FOUND HANDLER
          Url of page handling 'Link item not found' errors
    -->
    <setting name="LinkItemNotFoundUrl">
      <patch:attribute name="value">/ErrorPages/404.html</patch:attribute>
    </setting>
    <!--  LAYOUT NOT FOUND HANDLER
          Url of page handling 'Layout not found' errors
    -->
    <setting name="LayoutNotFoundUrl">
      <patch:attribute name="value">/ErrorPages/404.html</patch:attribute>
    </setting>
    <!--  ERROR HANDLER
          Url of page handling generic errors
    -->
     <setting name="ErrorPage">
      <patch:attribute name="value">/ErrorPages/Error.html</patch:attribute>
    </setting>
  </settings>
</sitecore>
</configuration>

These settings are already defined in the web.config file and changing them here will have the same effect, but I recommend adding patch config files as it will make your solution easier to update in the future.