Error Handling

Error Handling

No matter how much I believe that my code is going to handle things, inevitably something happens and an exception is thrown. It might be a timeout accessing a remote service or an offline database in the middle tier. On occasion, I haven’t accounted correctly for all of the edge cases that can occur when processing user input. Adding asynchronous callbacks to more of the ASP.NET application provides additional challenges in handling errors in a user-friendly way.

Allowing Custom Errors

If your user encounters an error with your ASP.NET application, you may be taking advantage of ASP.NET custom errors to redirect the user. You can provide a page with a look and feel consistent with the rest of the site that provides something more user friendly than a developer-focused error message. At the same time, you might log some information using tracing functionality so that you are aware of the frequency with which users are encountering errors. Then you can follow up to try and improve the experience and prevent the error from occurring in the future.

With asynchronous postbacks and partial rendering, an exception can go back to the script that initiated the callback, and the default behavior is to show the user the error message. This happens even if you have custom errors enabled for your application. Part of the reason that the default behavior is not to fol-low redirects is the potential to navigate away from a page where a user has invested time updating a state in stages without navigating between pages. Your objective is to keep the user’s data on his page while showing him an error. When redirected to an error page, the user’s reaction is to hit the Back but-ton. This can put the browser in a state before it begins interacting with the page, thereby losing the user’s data. The ASP.NET team has released prototypes of methods for putting interim stages in the browser’s history, but these have not been incorporated into an ASP.NET AJAX release yet.

When an error occurs in this condition, you don’t want the user to be redirected to a custom error page. Instead, you can provide an endRequest event handler and alert the user to the error without redirecting to an error page. Then you can return the user to the view they had before the error occurred to continue working with the application. The following JavaScript code demonstrates binding to the

function pageLoad() {
  Sys.WebForms.PageRequestManager.getInstance().add_endRequest("endRequestHandler");
}

function endRequestHandler(sender, arg) {
    if (arg.get_error() !== null) {
        //alert user of problem and continue
        arg.set_errorHandled(true);
    }
}

If your application doesn’t need to recover from error conditions in this way, you can set the allowCustomErrorsRedirect property of the ScriptManager to true to continue following the custom error handling that would occur when not using partial page rendering.

<asp:ScriptManager runat="server" ID="ScriptManager1"
AllowCustomErrorsRedirect="true" >

Handling Errors during Asynchronous Postback

ASP.NET AJAX allows you to trap an error that occurs during asynchronous postback processing. You can provide a static error message so that the user doesn’t have to see a potentially confusing .NET exception, or you can provide an error handler that will run on the server and do something more to recover from the error condition.

The ScriptManager has an AsyncPostBackErrorMessage property that can be used instead of the actual exception message that would normally be displayed.

<asp:ScriptManager runat="server" ID="ScriptManager1"
AsyncPostBackErrorMessage="Please try again tomorrow." >

The following code shows binding an event handler to the error event before it is sent to the client. It doesn’t simulate an error but shows how to set up your own code to run when an error occurs. The exact nature of how to recover gracefully is up to you, although I should admit that it is not always feasible to do so. Sometimes, trying to recover from a problem puts the user in a position of repeating the action even though server resources are not available to process the request. Staging an infinite loop for the user is not an optimal application experience. Just remember to spend a reasonable amount of time in testing error conditions to minimize the chance of unexpected behavior that may upset users.

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<script runat="server">
private void OnAsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e) {
    ScriptManager.AsyncPostBackErrorMessage = "Please call me at home. Something 
erroneous has occurred.";
} 
</script>

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head id="Head1" runat="server">
  <title>Error Handling</title>
</head>
<body>
  <form id="Form1" runat="server">
  <asp:ScriptManager runat="server" ID="ScriptManager" 
EnablePartialRendering="true" OnAsyncPostBackError="OnAsyncPostBackError">
  </asp:ScriptManager>
  </form>
</body>
</html>

Asynchronous Timeout

The ScriptManager allows you to customize how long to wait in the browser before considering the request orphaned and timing out. By default, the client will wait for the server to close the connection before assuming that the request has been abandoned. To specify a new default timeout for all requests, you use the AsyncPostBackTimeout property. The unit of measurement is milliseconds.

<asp:ScriptManager runat="server" ID="ScriptManager" EnablePartialRendering="true"
AsyncPostBackTimeout="3000" >