Tuesday, June 05, 2012

Global Error Handling in SharePoint 2010


Correct exception handling is an essential part of reliable and maintainable SharePoint applications. Most of the times in development stage of SharePoint 2010 we encounter the error “An unexpected error has occurred”. It always recommended code snipped always embedded in try catch block to log the errors. SharePoint also provides you the facility to map your custom page which can be displayed whenever there is any error. I have already explained this in my previous article of “UpdateMappedPage in SharePoint 2010” function.

There are several locations where an unhandled exception can occurred and there are different ways to capture the exception as explained below:

Page: In a SharePoint application, if an unhandled exception is not caught, it propagates to the page that was requested by the end user. SharePoint has a built-in global exception handler that will catch any unhandled exceptions and redirect the user to an appropriate error page (error mapped page). It is possible to handle unhandled exceptions in custom pages by responding to the Page_Error event provided by ASP.NET. The error page should not display any unhandled exception details to the end user because this can pose a security risk.

WebService: Within the Web service, you should catch all unhandled exceptions, log them and return a general exception message. This is also called exception shielding

WebPart: By default, if an unhandled exception occurs within a Web Part, the exception propagates to the Web page and triggers the unhandled exception handler of the page. This is not always the desired behavior. For example, it is possible in SharePoint to give end users the option of composing their own pages using Web Parts. When a Web Part throws an exception, it is difficult for the user to remove that Web Part from the page. To avoid this problem, you can implement an unhandled exception handler in this location

Purpose

It is not always possible to predict all exceptions that can occur with a SharePoint 2010 web site. Even sometimes developer do not include there code in proper try catch blocks causing the unhandled exception to occur. Therefore, we must implement handlers at system boundaries for unhandled exceptions. In general, exception handling for a SharePoint application is very similar to ASP.NET application. We can simply handle errors from the Application_Error function in the Global.aspx file; but in SharePoint, it never reaches that function; we can override this function by following way by creating our own http module.

Implementation

Step 1: Create an interface MyExceptionHandler using an IhttpModule interface.
An HTTP module is called on every request in response to the BeginRequest and EndRequest events. As a result, the module runs before and after a request is processed.

public class MyExceptionHandler : IHttpModule
{
}

Step 2: The Init function is called with the HttpApplication object. Attach an event handler to the HttpApplication.Error event.

/// <summary>
/// Attach an event handler to the HttpApplication.Error event
/// </summary>
/// <param name="context">Your Application</param>

public void Init(HttpApplication context)
{
    context.Error += new EventHandler(Application_Error);
}

Step 3: Implement Application_Error function to log error. This method gets the exception information, go down in depth and find the first error that raised the exception. Create the error message with the error info and the stack trace and the following code uses Microsoft Enterprise Library’s Logging Application Block to log the error. We can also configure whether we want to keep the log in a database, or in a flat file, or in other places, it’s totally depend on how you configure your Logging Application Block. You can also add code to redirect the user to custom error page or just implement Error Mapping page using UpdateMappedPage function of Web Application (previous article “UpdateMappedPage in SharePoint 2010”).

/// <summary>
/// Implement Application Error object
/// Use this method to log errors using logging functionality
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Application_Error(object sender, EventArgs e)
{
    HttpContext Context = HttpContext.Current;
    Exception exception;
    for (exception = Context.Server.GetLastError();
            exception.InnerException != null;
            exception = exception.InnerException) { }

    string LogDate = DateTime.Now.ToString("ddMMyyyy-HHmmfff");
    Logger.Write(String.Format("Exception Occured: {0} : {1} : {2}", new object[] {
         exception.Source, exception.Message, exception.StackTrace}),
         "General", 5, 1, System.Diagnostics.TraceEventType.Critical, LogDate);
}

Step 4: Register MyApplication.dll which contains the Module MyExceptionHandler in GAC.

Step 5: You need to put your IHttpModule before SharePoint specific modules in your web.config or otherwise your error routines may not work as you would expect.

<modules runAllManagedModulesForAllRequests="true">
<remove name="AnonymousIdentification" />
<remove name="FileAuthorization" />
<remove name="Profile" />
<remove name="WebDAVModule" />
<remove name="Session" />

<add name="MyExceptionHandler" preCondition="integratedMode" type="MyApplication.MyExceptionHandler, MyApplication, Version=1.0.0.0, Culture=neutral,PublicKeyToken=a0c7fe7135c06a56" />

<add name="SPRequestModule" preCondition="integratedMode" type="Microsoft.SharePoint.ApplicationRuntime.SPRequestModule, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

<add name="SharePoint14Module" preCondition="integratedMode" />

<add name="StateServiceModule" type="Microsoft.Office.Server.Administration.StateModule, Microsoft.Office.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

<add name="PublishingHttpModule" type="Microsoft.SharePoint.Publishing.PublishingHttpModule, Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

</modules>

References: http://msdn.microsoft.com/en-us/library/ff647598.aspx

2 comments:

Jim Pollard said...

Sandeep,

Thanks for your post. Can you maybe make a video tutorial for this?

I'm already lost at step one. lol

I don't know how to "Create an interface MyExceptionHandler using an IhttpModule interface."

Thanks,

Jim

Sandeep Pawar said...

Hi Jim...
just create a MyExceptionHandler.cs file in ur myapplication project and derived that from ihttpmodule as shown in step 1 lol

next go on adding functions as shown in steps....

thanks