Thursday 18 June 2009

Handling exceptions from multiple UpdatePanels

In one of my previous posts I've already mentioned how to handle exceptions that occur within UpdatePanel on client side (see post). However, this did not cover server side error handling nor multiple UpdatePanels on one page.

Sometimes you may want to have on your ASP page multiple update panels or a large one containing multiple controls. The problem is that when an error occurs on update action you may find hard to localize the actual control that generated the error causing event. This may be required in some situations e.g. to display error message next to the control responsible for the exception.

Let's take a look at some code. Here is a sample ASP page with a ScriptManager and 2 UpdatePanels. Each of the panels contains a button and a label for displaying errors:
<asp:ScriptManager ID="ScriptManager1" runat="server" 
onasyncpostbackerror="ScriptManager1_AsyncPostBackError">
</asp:ScriptManager>

<!-- First Update Panel -->
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="B1" runat="server" Text="B1" onclick="B1_Click" />
<asp:Label ID="Label1" runat="server"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>

<!-- Second Update Panel -->
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<asp:Button ID="B2" runat="server" Text="B2" onclick="B2_Click" />
<asp:Label ID="Label2" runat="server"></asp:Label>
</ContentTemplate>
</asp:UpdatePanel>
As you can see the ScriptManager has an error handler defined (line 2) and both buttons have click handlers assigned. The error labels are empty on entry.
Here is Code Behind for that page:
  protected void B1_Click(object sender, EventArgs e)
{
throw new Exception("Exception from Button1");
}

protected void B2_Click(object sender, EventArgs e)
{
throw new Exception("Exception from Button2");
}

protected void ScriptManager1_AsyncPostBackError(
object sender, AsyncPostBackErrorEventArgs e)
{
// Do smth with the error e.g log it
}
Clicking on any of the buttons will cause an Exception. The exception message varies for each button. In my example the error handler for script manager does nothing but you can do whatever you need with the caught error e.g. log it.

Now, let's handle the error on client side. The following code will register client side error handler, which will display a message from the thrown exception next to appropriate button:
// Register EndRequest handler for ScriptManager
Sys.WebForms.PageRequestManager.getInstance().
add_endRequest(EndRequestHandler);

function EndRequestHandler(sender, args)
{
// If there is an unhandled error
if (args.get_error() != undefined)
{
// Get id of the control that fired the error-causing action
var senderControlId = sender._postBackSettings.sourceElement.id;

// Get Label next to the source control
var errorLabel = document.getElementById(senderControlId).
nextSibling.nextSibling;

// Set error message in appropriate control.
// You may want to remove the user-unfriendly part of the
// message that was added by Script Manager
errorLabel.innerHTML =
args.get_error().message.replace
('Sys.WebForms.PageRequestManagerServerErrorException: ', '');

// Mark the error as handled
args.set_errorHandled(true);
}
}

That's it. To make it work just place the JS code on your ASP page.

No comments: