Belangrijke mededeling over deze pagina:

Deze pagina is niet beschikbaar in het Nederlands en daarom wordt de Engelse versie van het artikel getoond. Dit komt vooral voor bij technische artikelen.

When Sitecore can't find the requested item, it will redirect the user to the page that is configured in the setting ItemNotFoundUrl.
The problem is that redirecting will return an HTTP status code 302 (Moved Temporarily) and what we really want is the status code 404 (Not Found).

I've seen solutions where people will set the status code on the 'ItemNotFound' page.
That does not solve anything because the client will still be redirected to the ItemNotFound page and the initial request will not be marked as not found.

To solve this problem you can implement this custom pipeline processor.
It overrides the method that is called when Sitecore redirects the client to the ItemNotFound page.
Instead of redirecting, it does an HTTP request to retrieve the content of the ItemNotFound page and then it writes it to the client together with a 404 Not Found status code.

Keep in mind that:

  • The hostname of your website should be available on the server (some servers don't have a DNS, in that case you can add it to the hosts file)
  • Information about cookies is not submitted during the internal request of the ItemNotFound page, so if you have personalised information on that page, it will not work

To implement my solution,
add this to your include config file or add the processor to your web.config as a replacement of the default ExecuteRequest processor:

<pipelines>
  <httpRequestBegin>
    <processor type="ParTech.Library.Pipelines.ExecuteRequest, ParTech.Library" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel']"/>
    <processor type="Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel">
      <patch:delete />
    </processor>
  </httpRequestBegin>
</pipelines>

Add this class to your solution:

namespace ParTech.Library.Pipelines
{
    public class ExecuteRequest : Sitecore.Pipelines.HttpRequest.ExecuteRequest
    {
        protected override void RedirectOnItemNotFound(string url)
        {
            var context = System.Web.HttpContext.Current;

            try
            {
                // Request the NotFound page
                string domain = context.Request.Url.GetComponents(UriComponents.Scheme | UriComponents.Host, UriFormat.Unescaped);
                string content = Sitecore.Web.WebUtil.ExecuteWebPage(string.Concat(domain, url));

                // Send the NotFound page content to the client with a 404 status code
                context.Response.TrySkipIisCustomErrors = true;
                context.Response.StatusCode = 404;
                context.Response.Write(content);
            }
            catch (Exception)
            {
                // If our plan fails for any reason, fall back to the base method
                base.RedirectOnItemNotFound(url);
            }

            // Must be outside the try/catch, cause Response.End() throws an exception
            context.Response.End();
        }
    }
}

The result in Firebug after requesting a non-existing item:

11 Reacties

  • Door Allan Koch op 6/13/2014 om 3:07 PM

    Works like a charm! Thank you for sharing

  • Door Ruud van Falier op 3/10/2014 om 3:29 PM

    Thanks for pointing that out, Venkata.
    I was not aware of this setting.
    There would still be an advantage of using the pipeline processor because you don't have to set the status code in your 404 page logic, but this setting is definitly a very good alternative in most cases.

  • Door venkata phani abburi op 3/8/2014 om 6:07 PM

    there is a sitecore setting RequestErrors.UseServerSideRedirect. by setting this to true, Sitecore will not issue a 302. but for this to work correct we need to create a page named 404 in sitecore and set the status code on that page rendering. Just sharing no need to change the existing pipelines.. Sitecore already thought of this.

  • Door Ruud van Falier op 1/15/2014 om 4:36 PM

    Mounir,

    The errors that you posted are Analytics errors and in no way related to the code from this blog post.

    Cheers

  • Door mounir zarkan op 1/15/2014 om 4:20 AM

    hi,

    this doesn't work on my staging environment, I'm getting analytics errors,

    [moderator removed errors for the sake of readability...]

  • Door A.S. op 8/23/2013 om 9:25 PM

    Add
    context.Response.TrySkipIisCustomErrors = true;

    before
    context.Response.StatusCode = 404;

    Otherwise I was getting "The virtual path 'null' maps to another application, which is not allowed." error.

  • Door Ruud van Falier op 4/19/2013 om 2:19 PM

    Hi James,

    I have made a note about this and will into this. When I have an answer I will update the blog post.

    Cheers

  • Door James Gardner op 3/28/2013 om 2:33 AM

    Thanks Ruud, nice solution. I tried a few other suggested ways but none worked as well as this.

    One question I did have (and it isn't limited to your solution) is that missing images also end up being processed by the 404 handler (though not by the new code) and thus end up on the site with a link to the "pagenotfound" page rather than to where the image should be in Sitecore. Any idea how to get around this? I couldn't see anywhere that I could check if it was a media item and thus handle it differently.

  • Door Ruud van Falier op 3/5/2013 om 5:07 PM

    @Stijn: Thanks :-)

    @Alen: You are absolutely right and I've noticed this myself too. If you look at my later blogs, you'll see that I've already started using the method you mentioned. Thanks for your input!

  • Door Alen Pelin op 2/19/2013 om 5:07 PM

    I'd not recommend using <patch:delete /> for stock processors. The following solution is more elegant:

    <processor type="Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel">
      <patch:attribute name="type" value="ParTech.Library.Pipelines.ExecuteRequest, ParTech.Library" />
    </processor>

  • Door Stijn op 1/28/2013 om 5:07 PM

    Thanks a lot for sharing this solution. Works as a charm!

Plaats een reactie