Implementing a Site-Wide Error Handler for DataSources

I’m a developer that hate “cut and paste”. While it get the lines of code per day up, it is excessively and needlessly expensive. For AspNet, I tend to favor minimal code pages (if possible code-less pages) which often end up with a Asp:??DataSource working with Grids, DropDownLists, etc.

 

One of the issues is error handling – an item that can often double the code in an application. In some cases it is possible to write a few static methods and have error handling implemented across a entire website with no risk of some item not having error handling.  This code example deals with ObjectDataSource (what is often used for calls to WCF)

 

I use Master Pages, so life is simple with the addition of a single line in the Master Page(s) as shown below:

protected void Page_Load(object sender, EventArgs e)
{
    Utilities.ApplyObjectDataSourceErrorHandling(this.Controls);

This calls this simple piece of code to add error handlers to all ObjectDataSources used:

public static void ApplyObjectDataSourceErrorHandling(ControlCollection ctlSet)
{
    foreach (Control ctl in ctlSet)
    {
        if (ctl is ObjectDataSource)
        {
            ObjectDataSource ods = ctl as ObjectDataSource;
            ods.Updated += new ObjectDataSourceStatusEventHandler(ods_Exception);
            ods.Selected += new ObjectDataSourceStatusEventHandler(ods_Exception);
            ods.Deleted += new ObjectDataSourceStatusEventHandler(ods_Exception);
            ods.Inserted += new ObjectDataSourceStatusEventHandler(ods_Exception);
        }
        else if (ctl.Controls.Count > 0)
        {
            ApplyObjectDataSourceErrorHandling(ctl.Controls);
        }
    }
}

All of the exceptions are handled the same way. The event handler is below and looks for a Asp:Literal to put the Exception message into.

static void ods_Exception(object sender, ObjectDataSourceStatusEventArgs e)
{
    if (e.Exception != null)
    {
        Page mypage =HttpContext.Current.CurrentHandler as Page;                
        ShowExceptionInFeedback(mypage.Controls,e.Exception);
        e.ExceptionHandled = true;
    }
}

There was one gotcha – the sender is NOT the ObjectDataSource control but an isolated ObjectDataSourceView, so we have to grab the page through the handler and then search it for where we display the message.

static void ShowExceptionInFeedback(ControlCollection ctlSet, Exception exc)
{
    foreach (Control ctl in ctlSet)
    {
        if (ctl is Literal && ctl.ID == "Feedback")
        {
            Literal fbm = ctl as Literal;
            fbm.Text = exc.Message;
            return;
        }
        else if (ctl.Controls.Count > 0)
        {
            ShowExceptionInFeedback(ctl.Controls, exc);
        }
    }
}

In the above case, you are displaying the exception message to the user which is normally not the best practice. A better recommendation would be to use custom obfuscation text for each type of exception expected using a switch, with a default of “Unexpected Error” for what does not match.

 

You now have site-wide consistent error handling that is strictly enforced (by code).

Comments

Popular posts from this blog

Yet once more into the breech (of altered programming logic)

Simple WP7 Mango App for Background Tasks, Toast, and Tiles: Code Explanation

How to convert SVG data to a Png Image file Using InkScape