Sitecore 404 without 302

It’s a well known issue that when Sitecore displays a 404 page, it’s done by doing a 302 redirect to the 404 page, hence the 302 status code is thrown before the 404.

The behavior is partially because of the way .net handles redirects internally. But fortunately you can overcome it pretty easily.

My colleague Anders Laub came up with this extension to the Sitecore httpRequestBegin pipeline.

By adding a processor to the pipeline you can switch the missing item with a 404 item inside Sitecore. The item in Sitecore will then have a sublayout that will throw the 404. In effect, Sitecore (or .net) will not know that there is a page missing and will continue the business as usual. It’s up to us developers to handle the 404. Just like we like it.

First the httpRequestBegin processor:

  <processor type="Sitecore.Pipelines.PreprocessRequest.CheckIgnoreFlag, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel" />
  <processor type="MyCode.Custom404ResolverPipeline, MyDll" />

The processor is added just after the ItemResolver. The ItemResolver returns null if the item is not found.

We then switch the missing item with our 404 item:

public class Custom404ResolverPipeline : HttpRequestProcessor
  public override void Process(HttpRequestArgs args)
    Assert.ArgumentNotNull(args, &quot;args&quot;);

    // Do nothing if the item is actually found
    if (Sitecore.Context.Item != null || Sitecore.Context.Database == null)

    // all the icons and media library items 
    // for the sitecore client need to be ignored
    if (args.Url.FilePath.StartsWith(&quot;/-/&quot;))

    // Get the 404 not found item in Sitecore.
    // You can add more complex code to get the 404 item 
    // from multisite solutions. In a production 
    // environment you would probably get the item from
    // your website configuration.
    Item notFoundPage = Sitecore.Context.Database.GetItem(&quot;{DFE03D7A-00B9-4C15-8AB7-482D82B3484E}&quot;);
    if (notFoundPage == null)

    // Switch to the 404 item
    Sitecore.Context.Item = notFoundPage;

The page we switched to needs to have a sublayout that will do the actual 404 return code:

public partial class _404 : System.Web.UI.UserControl
  protected void Page_Load(object sender, EventArgs e)
    HttpContext.Current.Response.StatusCode = (int)HttpStatusCode.NotFound;
    HttpContext.Current.Response.TrySkipIisCustomErrors = true;
    HttpContext.Current.Response.StatusDescription = &quot;Page not found&quot;;

Remember to set the TrySkipIisCustomErrors or your 404 page will be ignored by IIS 7.5.


About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in c#, General .NET, Sitecore 6 and tagged , , , , , . Bookmark the permalink.

12 Responses to Sitecore 404 without 302

  1. John West says:

    In a multisite solution, you may want different 404 pages for each site. You can add a notFound attribute to the /configuration/sitecore/sites/site elements in the web.config file to store the ID (or path, or relative path from the home item, etc.) of the item to handle 404 for that site, and an extension method to allow Sitecore.Context.Site to expose that value.

    Very important that the 404 page actually return 404 as you have shown – otherwise the 404 page would return 200.

  2. briancaos says:

    You are right. This is a prototype to show how you can solve the issue with as little code as possible.

  3. Benjamin V says:

    You also have the parameter UseServerSideRedirect to avoid the 302 error when an item is not found it use a Server.Transfer

  4. John West says:

    If I remember correctly, you can transfer to a file, but not to an item. If you set UserServerSideRedirect to true, then I think all error pages (including 404) for all sites must be files, not items.

  5. Vikram says:

    I created a sample as you said here & its working fine.
    Only thing I would like to know is that how I can update the URL to /404.aspx.

  6. briancaos says:

    You could do a Response.Rewrite on your 404 user control to a page in Sitecore with the URL 404.
    Remember that the new 404 page should also return status code 404.

  7. sderico1 says:

    Do you know a good way to handle static .aspx pages that do not have a sitecore item assigned to them other than putting them in some kind of ignore file so they stay out of the pipeline/assigning some empty (but existing!) items to correspond to them (would like to handle this programmatically instead of hardcoding files/adding filler items).

  8. briancaos says:

    The correct way is to use the IgnoreUrlPrefixes setting in web.config. You can specify a folder where all of your non-sitecore pages resides. Or you can put the all in /sitecore modules/, Sitecore will ignore these as well.

  9. sderico1 says:

    That’s a good idea but then if a user enters anything with /path/doesntexist won’t they get some undefined result? Check this idea that checks Sitecore.Context.Page.FilePath. It may be a better idea to use the second suggested approach because Context.Site seems to be null for user controls’ full paths.

  10. Pingback: Handling 404 in a Sitecore multisite solution and avoid 302 redirects | Laub plus Co

  11. Henrik Stidsen says:

    I found a small problem with this module today. If your page has items with login restrictions, it will trigger the 404 pipeline if the user does not have access to it – Sitecore resolves the item to null if the user does not have read permissions.

    I added “if (args.PermissionDenied) return;” as the first line in the Process method to fix the problem.

  12. Pingback: Handling 404s in Sitecore | Andy Burns' Blog

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s