SharePoint 2010 ‘Page not found (404)’ page the way it should be

, , , , ,

Custom 'Page not found' page in SharePoint 2010
More and more frequently SharePoint is being used as the platform for Internet-facing websites. Not surprisingly the latest version of SharePoint is greatly improved making it event better solution for creating public websites. Although Microsoft did a great job in the Web Content Management area of SharePoint there are still a few shortcomings, one of which are custom ‘Page not found (404)’ pages. Find out how to do things right when moving your website to the SharePoint platform.

See no evil…

‘Page not found (404)’ pages are one of those things that no one wants to see but we all need it. No matter how hard you will try and how often you will verify your content for dead links, it’s just a matter of time before someone mistypes the URL. Although SharePoint won’t break immediately this is what you will see by default:

Default SharePoint 2010 ‘Page not found’ page

Far from perfect isn’t it? It isn’t even good to be honest. Especially if you’re considering to use SharePoint as the platform for your public website it’s definitely one of the things you have to do something about. So what are the options?

What do you really need?

Before we take a look at what SharePoint has to offer let’s have a quick glance at how a proper 404 page should be like.

First and the most important of all it should make clear to the user that the requested page doesn’t exist – no matter if it’s the user’s fault by mistyping the URL of it’s accessed via a dead link. And because it’s not the page that the user needs it should be minimalistic, simple and contain only the necessary elements.

The second important this is, that it should be clear to the user that he is still on the site. This means that the 404 page should have User Experience consistent with the rest of the site.

If you look from the user point of view, the 404 page is rarely the destination. As the name says, it’s an error page meant to communicate that something didn’t go as intended. That is exactly why a good 404 page should be more than only an error message and should help the user to find what he is looking for. If you’re using meaningful URL’s, which you should be using, you can use the missing URL to search for related information on your site and present those results to the user.

Seeing a 404 page is confusing for most users and you shouldn’t make it even more confusing. This is why it is important not to change the URL so that the user can see which URL he requested.

Finally, from the technical point of view, the 404 page should return the 404 HTTP status code. This will allow search engines and all other automated software to properly handle the page and decide whether they really want to process the undesired response or not.

So what are the options for good 404 pages in SharePoint?

PO(S)H

When looking at what SharePoint offers out of the box for custom ‘Page not found’ pages, there are not that many options. To be honest there is only one option which allows you to set a 404 page on the Web Application level. The worst part of it is, that SharePoint requires that page to be Plain Old (Semantic) HTML only. Additionally this page must be deployed to the LAYOUTS folder. Such approach means that not only the custom ‘Page not found’ page has limited capabilities but also that there is no easy way for content managers to update the contents of that page.

Custom ‘Page not found’ page created using static HTML

Once you get everything in place there is one more surprise for you. Let’s take a look at how the 404 page looks like when you mistype the file extension:

HTML source of a ‘Page not found’ page

The HTML is being encoded!

So are there any alternatives to make a proper 404 page or is it something that we should learn live with?

Alternative solutions

One of the common workarounds for the standard capabilities is to create a custom ‘Page not found’ page which redirects to a regular SharePoint Publishing Page. Such page can be easily maintained by the content editing team and has a User Experience which is consistent with the rest of the site. The downside of this approach is that the URL in the browser is being switched with the URL of the error page what might be confusing to the user. Additionally automatic redirections are frequently seen as inaccessible what makes it not the most user friendly solution out there.

A slight variation of this approach is a custom HTTP Module which intercepts all 404 responses and redirects to the ‘Page not found’ page instead. While this approach deals with the issue of client-side redirect it still has some downsides. The 404 response code is replaced by a redirect status code which might be processed by search engines. Additionally the original URL is being replaced with the URL of the error page what might confuse the user.

There is however a better way…

A proper SharePoint 2010 404 page

Recently I’ve done some research on custom 404 pages in SharePoint 2010 and found out that all you need to have to create a proper 404 page are a custom HTTP Module, a Publishing Page and a custom Web Part. Here is how it works.

First you create a custom HTTP Module which will intercept all 404 responses:

public class PageNotFoundHttpModule : IHttpModule
{
    private HttpApplication app;
    private string pageNotFoundUrl = "/pages/page-not-found.aspx";

    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        app = context;
        app.PreSendRequestContent += new EventHandler(app_PreSendRequestContent);
    }

    void app_PreSendRequestContent(object sender, EventArgs e)
    {
        HttpResponse res = app.Response;
        HttpRequest req = app.Request;

        if (res.StatusCode == 404 &&
            !req.Url.AbsolutePath.Equals(pageNotFoundUrl, StringComparison.InvariantCultureIgnoreCase))
        {
            app.Server.TransferRequest(pageNotFoundUrl);
        }
    }
}

This module checks if the response status code is 404 and the URL is different than the URL of the ‘Page not found’ page. If that is the case the request is being transferred to the ‘Page not found’ page. This is better than the standard redirect since it allows you to keep the original URL in the browser.

Important: Since you’re replacing the URL be careful what kind of functionality you provide on the error page. Rewriting URLs is not supported in SharePoint and might result in breaking some functionality so you should always test your solution before deploying this in production.

The next step is to create the ‘Page not found’ Publishing Page – nothing special here.

If you test your solution now you will see that you are almost there:

Custom Publishing Page displayed as ‘Page not found’ page

Although your custom ‘Page not found’ page is being displayed with the original URL (1), the response code is set to 200 OK (2) which is different than the 404 code we expected. This is caused by the request transfer that takes place in our HTTP Module. Unfortunately the response code cannot be set directly after calling the transfer since it’s being set later in the Page execution cycle. And this is exactly where our custom Web Part fits in:

public class PageNotFoundWebPart : WebPart
{
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        Page.Response.StatusCode = (int)HttpStatusCode.NotFound;
    }
}

By placing the Web Part as showed above the response code is being changed to 404 as expected:

Custom ‘Page not found’ page displayed with the proper 404 response code

No matter if the non-existing URL is caused by wrong page name or a faulty extension the HTTP Module will intercept the 404 response and will display your custom ‘Page not found’ page with the 404 response code – exactly as you would expect it to work.


Possibly related posts

14 Responses to “SharePoint 2010 ‘Page not found (404)’ page the way it should be”

  1. Servé Hermans Says:

    Hey Waldek, thanks for sharing. I am going to try this out myself in a couple of minutes. ;-) Next, I am planning to add a web part that provides an alternative using Search.

  2. Waldek Mastykarz Says:

    @Servé: you're welcome. search based on 404 url is definitely a great improvement. The downside is that out of the box SharePoint doesn't really do URL-based search suggestions so you would have to do some URL processing to get desired results.

  3. Servé Hermans Says:

    I was getting a bit frustrated as the page did not work. So I just rewrote the http module to output just "hello" (my favourite). Surprise: it works when you type in a valid URL but still shows a 404 page with an invalid URL. It has nothing to do with your module, SharePoint or IIS but with a setting in your browser.

    This is what visitors need to do: turn off the "Show friendly HTTP error messages" in your IE internet options -> Advanced tab.
    Else you will still see a "404" page rendered by the browser (as the browser is the last one in the chain who still responds to the http status code).

    Also in Google Chrome you will need to change the setting to see the custom 404 page: Advanced options -> Use a webservice to lookup navigation errors (or something like that). Uncheck.

    Maybe it is better to not return the 404 status code by not adding that last web part unless it is more important to you that Search engines will stop crawling dead links (eg on Internet facing sites)…

    If you are a real FAST expert you might want to put something on your page that FAST recognizes. Eg extend the content processing pipeline.

  4. Waldek Mastykarz Says:

    @Servé: this is pretty odd, since no matter the setting the 404 page using exactly this technique works on the mavention.nl website. If I'm correct there is a limit that an error page should be that large. If the page is under that size the browser will take over and will display its own 'friendly' HTTP error page.

  5. Bhushan Gawale Says:

    Hi Waldek,
    thanks for sharing this and useful tip
    but one question :
    this code works pretty fine when you type in ivalid .aspx page urls but when you type in invalid web url (server relative) then shows default 404 error page , why?

    for example : If I type in http://www.yoursite.com/Pages/invalidpage.aspx then code works fine and redirect users to your custom page not found page but
    If I type in url like http://www.yoursite.com/invalidweb
    then this shows 404 status page directly

    is this something with SP IIS pipeline? or with SPModule , becuase in second casedebugger dont even come to custom HttpModule

  6. Prasham Says:

    Hi Waldek,
    thanks for sharing this and useful tip
    but one question :

    this code works pretty fine when you type in ivalid .aspx page urls but when you type in invalid web url (server relative) then shows default 404 error page , why?

    for example : If I type in http://www.yoursite.com/Pages/invalidpage.aspx then code works fine and redirect users to your custom page not found page but
    If I type in url like http://www.yoursite.com/invalidweb
    then this shows 404 status page directly

    is this something with SP IIS pipeline? or with SPModule , becuase in second casedebugger dont even come to custom HttpModule

  7. Venkatesh Says:

    Hi,
    It works for system page, but not for application page..
    for example : If I type in http://www.yoursite.com/Pages/invalidpage.aspx then code works fine and redirect users to your custom page not found page but
    If I type in url like http://www.yoursite.com/_layouts/appname/invalidweb
    then this does not show custom 404 status page. Is there any fix for this

  8. Justin Says:

    hi Waldek,
    the HTTPModule seems like it might be a good solution for us – thanks for sharing! BTW – I ran into a similar problem as your encoded HTML page that you display above and after resolving the issue for myself by opening the file outside of Visual Studio to remove the Byte Order Marker (BOM), I can't help wondering if that may have been your issue as we. Here is a link to where I learned about the BOM issue: http://andreasglaser.net/post/2009/03/15/SharePoint-and-custom-404-Page-Not-Found-and-UTF-8-issue-with-Firefox.aspx

  9. George Durzi Says:

    Waldek, this worked great as is. I didn't experience any of the issues that the other commenters reported such as the module not working for a non existent web.

    After deploying, I would probably also add a robots.txt entry for the page not found publishing page, and also exclude it from the SharePoint search results.

    Thank you!

  10. Andrew Greaves Says:

    I found an alternative to the webpart to generate the 404. You can listen to this event in the HtppModule pipeline as well:

    void app_PostRequestHandlerExecute(object sender, EventArgs e)
    {
    HttpResponse res = app.Response;
    HttpRequest req = app.Request;

    if (req.Url.AbsolutePath.Equals(pageNotFoundUrl, StringComparison.InvariantCultureIgnoreCase))
    {
    res.StatusCode = 404;
    }
    }

  11. Waldek Mastykarz Says:

    Good one! Thank you for your feedback, Andrew!

  12. Mathew Says:

    Thanks Waldek, and thanks Andrew! Will be able to retract the web part, now.

  13. Morgan Says:

    Thanks for this post, it works fine, however, if the site collection has the URL (example) http://server/sites/mysite/ then it doesn't work with "private string pageNotFoundUrl = "/pages/page-not-found.aspx";". How can I get the site collection URL so the string would be "/sites/mysite/pages/.." instead? Thanks in advance.

  14. Waldek Mastykarz Says:

    @Morgan: Have you tried seeing if the SPContext.Current.Site is available?

Leave a Reply

Security Code:

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS
Copyright © 2007 - 2012 Waldek Mastykarz

Creative Commons License