One of the development challenges with SharePoint is setting up a generic error handler so that you can display a site-specific error page instead of the error pages displayed by SharePoint. Although SharePoint 2007 is built on top of ASP.NET 2.0/3.5, there are some facilities available in ASP.NET that don't work the same when run through SharePoint because of the way SharePoint handles most of the page-rendering events to facilitate loading dynamic content from the SharePoint database.
Typically in ASP.NET to implement an error handler you can implement a global.asax error handler and log the error and redirect to an error page. Global.asax events don't work the same way in SharePoint, and the error handler is not called. Instead what's needed is to implement a subclass of IHttpModule and then configure the web application to load it in response to errors.
To implement the error handler, first create the class ErrorHttpModule shown below. Provide your own implementation of the LogError and LogInfo methods to write to your chosen logger (I recommend log4net):
using System; using System.Configuration; using System.Web; namespace MikeKnowles.Cobalt { /// <summary> /// Generic error handler for a .NET or SharePoint 2007 web application. /// </summary> public class ErrorHttpModule : IHttpModule { public void Init(HttpApplication app) { app.Error += new EventHandler(Application_Error); } private void LogError(string message) { // TODO: write error message and stack trace of exception to your logger } private void LogError(string message, Exception ex) { // TODO: write error message and stack trace of exception to your logger } private void LogInfo(string message) { // TODO: write message to your logger. } public void Application_Error(object sender, EventArgs e) { Exception ex = HttpContext.Current.Server.GetLastError(); string message = "HttpContext.Current.Request.Path=" + HttpContext.Current.Request.Path + " "; if (ex != null) { message += ex.Message; ex = ex.GetBaseException(); } else { message += "HttpContext.Current.Server.GetLastError() is null"; } LogError(message, ex); String errorPagePath = ConfigurationManager.AppSettings["GeneralErrorPath"]; if (errorPagePath != null) { LogInfo("Transferring to " + errorPagePath); // transfer instead of redirect so the user still // has requested page in address box HttpContext.Current.Server.Transfer(errorPagePath); } else { LogError("Property GeneralErrorPath not found in web.config."); } } public void Dispose() { } } }
Next, register the module with ASP.NET by adding the dll as the first item in the HttpModules section in Web.config. If the module is not listed first then error handling will not work as expected in SharePoint - you will still see the SharePoint generic handler in certain situations even though your error handler was executed. You will need to modify the 4 part name to match the dll you will include the code within (shown below on multiple lines for readability):
<add name="ErrorHttpModule" type="Cobalt, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2a75bd97c63f6363" />
Finally, add the following key to the AppSettings section of Web.config and provide the path to an error page within your web application. If you don't have one, just create a static html page. The property below points to a file in the SharePoint _layouts folder. The error page can reside anywhere you like as long as it's reachable by ASP.NET. Within a SharePoint application, I recommend making this a static file and not a page within the SharePoint database so the error page will be displayed in the event there are problems with the database or connecting to the database:
<add key="GeneralErrorPath" value="/_layouts/FOLDERNAME/GeneralError.aspx" />