The Problem

You make heavy use of the UpdatePanel control to perform asynchronous postbacks, however, you've encountered an exception while processing the server-side code. The result will be a JavaScript error thrown by the AJAX library, as the exception wasn't handled, the AJAX Framework will thrown the exception and then browser will notify the user of the error, as shown below in the two screen shots below (Firefox is shown on the left and Internet Explorer 8 on the right). No doubt, the average user will have no idea what has just occurred.

image image

The Solution

Use the ScriptManager control to handle the exception prior to returning a response to the client. The ScriptManager control includes the event handler property AsyncPostBackError (OnAsyncPostBack from markup) and can be used to register event handlers that are invoked upon an exception being thrown during asynchronous postback operations. The following code fragment demonstrates an event handler method, note the property of type AsyncPostBackErrorEventArgs. We may use this property to retrieve details of the originally thrown exception.

protected void ScriptManager1_AsyncPostBackError(object sender, 
    AsyncPostBackErrorEventArgs e)
{
    
}

The AsyncPostBackErrorEventArgs object exposes a property of type Exception, coincidentally named Exception, which exposes the originally thrown exception. If we desire the original exception message to be returned to the client, we may do so by setting the AsyncPostBackErrorMessage property of the ScriptManager instance to the exception message, as shown below.

protected void ScriptManager1_AsyncPostBackError(object sender, 
    AsyncPostBackErrorEventArgs e)
{
    ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message;
}

Finally, the error message will be returned to the client within the response body, as shown below.

image

This is, of course assuming that the exception message was "An error occurred". The response body will be parsed by the client-side AJAX framework and the error will be detected, however, at this point, the error has not yet been handled. For this, we should bind an event handler to the client-side endRequest event of the PageRequestManager. For those of you who aren't familiar with the PageRequestManager, it manages all partial-page postback requests. Thus, by assigning an event handler to the end event of a partial-page postback we can handle the error and notify the user of the server-side error in anyway we desire. The client-side JavaScript code is shown below.

var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(EndRequest);

function EndRequest(sender, args)
{
    if (args.get_error())
    {
        alert(args.get_error().message);
        args.set_errorHandled(true);
    }
}

Note that an instance of the PageRequestManager must first be retrieved, as there can be only a single PageRequestManager present, which is created when the ScriptManager control is configured to support partial-page updates (the default behavior).

Finally, the code in its entirety is shown below.

<%@ Page Language="C#" AutoEventWireup="true" %>

<script runat="server">
    protected void Button1_Click(object sender, EventArgs e)
    {
        throw new Exception("An error occurred");
    }
    
    protected void ScriptManager1_AsyncPostBackError(object sender, 
        AsyncPostBackErrorEventArgs e)
    {
        ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message;
    }
</script>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager runat="server" ID="ScriptManager1"
            onasyncpostbackerror="ScriptManager1_AsyncPostBackError">
        </asp:ScriptManager>
        
        <script type="text/javascript">
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            prm.add_endRequest(EndRequest);
            
            function EndRequest(sender, args)
            {
                if (args.get_error())
                {
                    alert(args.get_error().message);
                    args.set_errorHandled(true);
                }
            }
        </script>
            
        <asp:UpdatePanel runat="server" ID="Update1">
            <ContentTemplate>
                <asp:Button runat="server" 
                    ID="Button1" 
                    Text="Click Me" 
                    onclick="Button1_Click" />
            </ContentTemplate>
        </asp:UpdatePanel>
    </form>
</body>
</html>

When the button is clicked, the following alert box will be displayed.

image

If everyone handled their errors the world would be a much better place!