Custom Error Pages in SharePoint

As I alluded to in my post Exception Handling in SharePoint, providing custom error pages is an integral step in an overall exception handling strategy. This is particularly important for public facing internet sites to portray a consistent brand for the site in any situation, however is also relevant for intra or extranet portals to provide a more user-friendly experience and to reduce confusion in the event of an error. In similar fashion to my post on Error Logging in SharePoint, the information already available on this topic is extensive so the need for me to blog the specifics is negligible. This post will however join the link between my 2 previous posts mentioned above by outlining the best resources available in this area for both SharePoint 2007 and 2010.

In the ASP.NET world this topic would barely rate a mention. Handling this matter is essentially as simple as ensuring the <customErrors> mode=”" attribute is set to “On” and the defaultRedirect=”" attribute is set to a valid error page. We can’t use this method in SharePoint however as SharePoint has its own error handling infrastructure which overrides this functionality.

What we do have are different ways in which we can achieve this functionality in both versions of the product. When we talk of error pages in a SharePoint context we can group them into two categories for the purpose of identifying ways in which they can be addressed; 404 Page Not Found error pages and any others (which can include but are not limited to 401 Access Denied errors, 500 HTTP Status errors and the like).

404 Page Not Found

Microsoft has a knowledge base article How to point to a custom 404 error Web page in SharePoint which covers both versions of SharePoint. One thing to note here however is that it’s not necessary to create a console application to carry out the command in SharePoint 2007 – you can also use a powershell command to achieve the same thing noted in Ian Morrish’s post Using PowerShell to set a custom SharePoint Error Page.

Another thing to note is that this method requires the specified file to be valid HTML larger than 512 bytes in size. The size limitation is to ensure friendly HTTP error messages are not triggered in the client. I’ve also seen minorly-invalid HTML rendering as text in the browser so this is another thing to look out for. One more gotchya was identified by Andreas Glaser in SharePoint and custom 404 Page Not Found and UTF-8 issue with Firefox which is worth consideration.

One downside to the method presented above is that you are limited to static HTML pages deployed to the _layouts/1033 directory (or which ever LCID is appropriate for your site). This results in branding elements needing to be implemented in the static HTML and ensures maintenance of the page is more complicated than it should be. The main advice here is to implement a redirect on that error page to a standard SharePoint page along the lines identified by Jingmei Li in How to create your own custom 404 error page and handle redirect in SharePoint 2007 (MOSS)?.

There is another line of thought however, predominantly outlined by Waldek Mastykarz in his posts Accessible 404 (PageNotFound) in Microsoft Office SharePoint Server 2007 and SharePoint 2010 ‘Page not found (404)’ page the way it should be. This advocates using an HTTP Module to redirect the user to a page managed in SharePoint. If you’re going to go down this path focus on the second article and pay attention to Andrew Greaves’ comment.

While I like Waldek’s approach and appreciate its thoroughness in its flexibility for working in all scenarios and its technical correctness, for most purposes using the other method would suffice (particularly in controlled internal environments).

Other Error Pages

While the handling of 404 errors is quite similar in both SharePoint 2007 and 2010, the same cannot be said for other errors. SharePoint 2010 excels in this area providing an easy to use method of assigning these custom error pages at the web application level. Todd Carter provides a post titled An Expected Error Has Occurred which is well worth a read and while the code snippets are identical, Ram Prasad Meenavalli’s post Mapping Custom Error Pages for SharePoint 2010 Site is a good extension to it. Mike’s post SharePoint 2010 Custom Error Messages for Public Facing Deployments is a quality post particularly in terms of 401 authentication errors and is worth a look as well.

Implementing custom error pages for SharePoint 2007 however is not so simple. There seems to be 3 camps of thought; firstly there is the HTTP Module method similar to that used with the 404′s outlined above. While its a little difficult to read and follow, this method is documented in Ketaanh Shah’s post MOSS / Sharepoint 2007 Custom Error Page and Access denied Page. Another option is using a control adapter as per Aapo Talvensaari’s post Custom Error Page Adapter although i’d be a little wary implementing the functionality in this manner. My favourite option is Jeremy Jameson’s Error Handling in MOSS 2007 Applications which advocates hooking into the Error event from a custom master page – nice and clean, however it’s only really appropriate for errors that occur once the page has been accessed – i’m guessing it wouldn’t be suitable to handle errors such as a 401 authentication error.

In the interests of completeness there was one other form of configuring custom error pages I came across on Heath Anderson’s Implementing SharePoint 2010 Custom Error Pages. It is relevant to IIS7 and claims to work in SharePoint 2010 (whether it would work on an WSS instance installed on IIS7 i’m not sure). It definitely looks like a reasonably nice and clean option to consider, however it requires modifications to the web.config file even after configuring via the IIS UI and thus would not be the perfect option in my opinion.

So as you can see there are a bunch of ways in which you can implement custom error pages for your SharePoint site no matter which version of the product you are using. All methods vary in terms of their difficulty, suitability and correctness however the main takeaway is to ensure that you do use one of the methods and ensure that your users have the most user-friendly experience if they counter an error on your site.

Exception Handling in SharePoint

I feel like i’m going to be opening a can of worms with this one. I’ve given it a fair bit of thought over time and for this post specifically. I’ve read a lot of guidance around the topic. For the most part, best practice exception handling is reasonably well covered in the ASP.NET space but starts to become a bit murky when you delve into the SharePoint sphere. Some of my own personal preferences clash slightly with other advice that exists and like anything to do with SharePoint, often circumstances may dictate the path you need to take.

As such, I was slightly hesitant to write this post. The reason I have is because exception handling seems to be one of the most poorly implemented (or at least forgotten/ignored) tasks in SharePoint development. It’s also an important task when you factor in user experience, performance and ability to monitor your deployed applications. I’ve seen some shockers; from potential exception-throwing lines of code going unmanaged in web parts which could  bring down the entire page, to swallowed exceptions that you’ll never even know are there. I’ve seen catch (Exception ex) blocks scattered everywhere and try-catch blocks used to control execution flow or used in place of pre-exception checks.

There is a lot of good information out there. MSDN has version-specific editions regarding Handling and Throwing Exceptions. There are some good articles written for .NET in general including Scott Mitchell’s Exception Handling Advice for ASP.NET Web Applications, Daniel Turini’s Exception Handling Best Practices in .NET and Russell Allen’s C# .net Exception Handling Best Practice – As Easy as 1, 2, 3?.

The general consensus tends to boil down to a few rules. Generally, the base exception classes (Exception, ApplicationException) shouldn’t be caught or thrown. Exceptions should only be handled if you can add value to how they’re processed, otherwise they should be allowed to bubble up the chain. Finally, exceptions should be reported so corrective action can be taken if nececssary – preferably using an existing framework such as the Exception Management Application Block.

The question is how these rules and surrounding information can be tweaked to be suitable for SharePoint projects. I’ll structure my comments around this by identifying some general rules and outlining where they’re applicable in a SharePoint context.

1. Never, ever swallow an exception.

Pretty obvious, but the following is a definite no-no.

try
{
    // code
}
catch { }

At the very least the error should be reported using error logging functionality, if not handled sufficiently. I have seen an instance whereby the exception was expected and superfluous to report – I wish I could find it now or even remember why to explain – but if this unlikely case ever occurs it should be properly documented in the code.

2. If you’re going to throw an exception, use throw;

A common piece of code I see goes something along the lines of:

try
{
    // code
}
catch (Exception ex)
{
    throw ex;
}

This is actually quite bad practice. The reasons why were highlighted in some of the links I mentioned earlier, but essentially by doing this you clear the stack trace which is very useful when debugging the exception down the track. You’re better off using the following:

try
{
    // code
}
catch
{
    throw;
}

3. Wherever possible handle the specific exception.

The most common form of exception handling I see is something along the lines of:

try
{
    // code
}
catch (Exception ex)
{
    // handle exception
}

The problem is this goes against the general philosophy behind exception handling. Lee Dumond’s post Friends Don’t Let Friends catch (Exception) explains this nicely.

If you know the object model, or at least know where to go to find the information, you’ll be able to find out which exception/s you should be handling. Take the GetList function in SPWeb. That page identifies clearly the exceptions that may be thrown so you should handle them appropriately.

try
{
    spList = spWeb.GetList("/Path/List");
}
catch (FileNotFoundException ex)
{
    // handle exception
}
catch (ArgumentException ex)
{
    // handle exception
}

An important point to note is that your catch blocks must go in order of most specific to least specific.

4. If you can check for a condition before it throws an exception, do so.

A common block of code you may see is something along the lines of:

try
{
    myString = listItem["MyField"].ToString();
}
catch (Exception ex)
{
    // handle exception
}

Sure, if MyField was never populated in the list item it would throw an exception when you attempt to convert it to a string, but why not check to see if it was populated in the first place?

if (String.IsNullOrEmpty(listItem["MyField"]))
{
    myString = listItem["MyField"].ToString();
}

5. You got to know when to hold ‘em, know when to fold ‘em.

Ok I may have stretched the poetic licence a bit there. What i’m talking about somewhat contradicts the rule regarding letting exceptions bubble up the chain to be handled at the application level. Consider you have a web part on a page, relatively non-critical to the page or application as a whole, a weather web part for instance. Do you really want the whole page to error out because it generated an exception? I wouldn’t begrudge you a global catch (Exception) in that instance.

On the flip side, imagine an event receiver that is processing a list item that is currently being added. The processing is necessary to complete the step of adding the list item, but the exception is caught, reported and held. The list item will exist, but the process did not complete, and depending on the level of reporting the user may never have a clue.

The point is you really need to use your best judgement when it comes to error handling in SharePoint. It’s hard to state a catch-all rule that can be applied across the board, often it will depend on context.

6. Determine the most appropriate form of logging and use it.

I would have preferred to state how errors should be logged in a SharePoint application much more definitively than this. The most important takeaway is to ensure that the errors are logged. The 2 most logical locations to log the errors would be the ULS or Event Log, however this may not always be appropriate. If these locations aren’t regularly monitored or accessible by the people who need to know about the errors, then it is essentially no better than swallowing the errors in the first place. Email, CRM, a database or even a SharePoint list are other potential locations that could be more accessible. Logging to a file on the file system makes little sense seeing if that is an accessible option you could just use the ULS. I write on this topic in more detail and explain my preference for logging to the ULS/Event Log using the SharePoint Guidance Library in my post Error Logging in SharePoint.

7. Use a custom error page.

Nothing looks worse on a public facing internet site or even an intranet application than when you get the ‘yellow screen of death’. Wherever possible you should display a user friendly message rather than an ugly generic error page. I explain the options available around this topic in my post Custom Error Pages in SharePoint.

That about covers it. Just thinking about this post made my head spin around in circles so it’s no wonder why a vast number of developers take the shortcut route and use global try-catch blocks with generic Exceptions. Hopefully this post sheds some light however on why doing so is a bad idea and that there are better options available to be leveraged. If anyone wishes to comment on the topic I’d be very interested in hearing opposing views and ideas – I’d still consider myself learning the best practice approach to exception handling at this point.

Follow

Get every new post delivered to your Inbox.