Accessible 404 (PageNotFound) in Microsoft Office SharePoint Server 2007

Every time you request a web page that doesn't exist, the web server provides you with a 404 (the web server response code for an non existing URL) page - an information page telling you that you've got it wrong. While some of your visitors, might be able to get to the information they are looking for either by correcting the URL or finding an alternative way to access the resource, it is a good practice to provide an information page which will help the average visitors to continue the navigation like nothing really happened.

A good 404 page should consist of:

  • User Experience (UX) consistent with the web site it's being served by
  • Short explanation of why the user has been redirected to this page and how can he browse further
  • The requested URL which is missing
  • A possibility for the user to report the broken link including a comment
  • Navigation options:
    • Back button
    • Link to the web site’s Sitemap
    • Search field (or link to the search page if no such field available)
    • Link to the Home Page

While some of these components could be easily done using static HTML, it is definitely easier to create such a page using the available server-side technologies.

Microsoft Office SharePoint Server 2007 ships with a custom PageNotFound page. Unfortunately it is really far from being usable and even further from being accessible. That's why SharePoint allows you to create and use your own custom PageNotFound pages.

Default SharePoint 2007 PageNotFound page

The biggest problem of 404 pages as supported by MOSS 2007 is lack of support for dynamic pages. Custom 404 pages must:

  • be static HTML pages
  • reside on the web server in the _layouts\<lcid> directory

This introduces two issues. First of all, because the page is a physical file stored on the web server, it can't be managed by the content editors. While you could develop a Feature which would make it all possible, it just seems awkward to me.

Second of all: a 404 page to use in SharePoint must be a static HTML page. While this is definitely acceptable for other error pages (if something isn't working correctly on the web server, you are very likely not to be able to serve any dynamic page, right?), it is quite odd for a 404 page. The idea behind a 404 page is to present it each time a user requests a page that doesn't exist. As the web server is still up and running, why not using it to provide your visitors with a consistent and really helpful page?

Many SharePoint developers create custom 404 pages by creating a simple static HTML page which redirects the visitor either using JavaScript or the meta element to a dynamic ASP.NET page. This approach has two major flaws.

First of all this technique relies on JavaScript and meta refresh: both optional technologies which can be easily disabled and are not accessible. Second of all, it causes an additional redirect. If the visitor wants to go back using the browser's Back button, he needs to hit it twice. If he's either inexperienced or cannot see what is actually going on, he keeps on landing on the custom 404 page.

So what would be a better way to provide a fully functional, accessible and user-friendly 404 page?

While researching this subject I have found out that you could achieve the required functionality by creating a custom HttpModule. By following the response codes (each server response comes with a response code) you can easily determine whether the requested item exists or not.

There is a response generated by the web server not only for pages but for all items processed by the web server so in case of SharePoint it's almost every single request. By comparing the extension of the file you could easily check whether it's a page that is missing or a file: you need to do that check if you want to prevent throwing a 404 page if one of the resources (eg. images) can't be loaded. Below you can see the example code I've put together.

public class WCM404HttpModule : IHttpModule  
{
  private HttpApplication app;

  #region IHttpModule Members

  public void Dispose()
  {
  }

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

  #endregion

  void context_PreSendRequestHeaders(object sender, EventArgs e)
  {
    HttpResponse res = app.Response;
    if (res.StatusCode == 404 &&
      res.ContentType.Equals("text/html",
      StringComparison.CurrentCulture))
    {
      string absolutePath =
        app.Request.Url.AbsolutePath.ToLower(
        CultureInfo.CurrentCulture);
      string lastSeg =
        app.Request.Url.Segments[app.Request.Url.Segments.Length - 1];
      if (absolutePath.EndsWith(".aspx") ||
        absolutePath.EndsWith("/") || lastSeg.IndexOf('.') == -1)
      {
        string language = "nl";
        string seg =
          app.Request.Url.Segments[1].ToLower(
          CultureInfo.CurrentCulture);

        if (seg.Equals("en/") || seg.Equals("nl/"))
          language = seg;

        res.Redirect("/" + language +
          "/pages/PageNotFound.aspx?url=" +
          app.Request.Url.AbsolutePath);
      }
    }
  }
}

It is very important that you display the 404 page only when necessary. The smarter you make your module, the more user-friendly it will be. By using the technique above you have the following wins:

  • Creating a 404 page in the same UX as the rest of the web site
  • As it's a normal Publishing Page the content editors can take for the contents themselves
  • You have access to the SharePoint object model and the ASP.NET framework, so you can use Web Parts to provide the required feedback and navigation
  • Use different 404 pages for different languages - this is one of the benefits of having the access to the SharePoint API
  • Being independent of JavaScript and meta refresh which is very important in accessible WCM solutions
  • Preserving the common navigation experience: hitting the Back button will take your visitors back the way they expect it to

Summary

Microsoft Office SharePoint Server 2007 ships with a framework for developing Web Content Management solutions. Although it contains rich functionality out of the box, it requires some extra effort to deliver accessible WCM solutions. Configuring custom 404 pages is one of the areas when using the standard framework is insufficient. Because MOSS 2007 is an application framework however, you are free in developing your own mechanisms to provide rich and user-friendly 404 pages.

Technorati Tags: SharePoint, SharePoint 2007, MOSS 2007, WCM

Comments

comments powered by Disqus