If you work with AJAX for any length of time you will find that no matter what the exception thrown in the code behind the message displayed to the user is “Exception has been thrown by the target of an invocation.” Not very useful.

My approach to debugging the exception had been to comment out the UpdatePanel, recreate the exception and see the real error. But this doesn’t work at all when the code is deployed to the end-user.
So the solution is to capture the AsyncPostBackError event of the ScriptManager as shown here:

Then in the code for this event (code behind) we can change the AsyncPostBackErrorMessage to the actual error message in the exception.
protected void ScriptManager1_AsyncPostBackError(object sender,AsyncPostBackErrorEventArgs e)
{
if (e.Exception != null && e.Exception.InnerException != null)
{
ScriptManager1.AsyncPostBackErrorMessage = e.Exception.InnerException.Message;
cApp.LogExceptionNoThrow(e.Exception.InnerException);
}
}
Note that I also log the exception which includes the stack trace so I can later research the problem.
One further enhancement would be to replace the alert box with a label on the page. To do this I first wire up an event in JavaScript to capture the return from an Ajax call. So here I am registering the JavaScript function “endRequest” to be called at the end of an AJAX request.
function pageLoad(sender, args) {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
}
And in my endRequest function I set the label and turns off the alert box.
function endRequest(sender, args) {
if (args.get_error() != undefined) {
var lbl = $get('<%= this.lblMessage.ClientID %>');
lbl.innerHTML = args.get_error().message;
lbl.style.color = 'Red'
// This will stop the alert box from displaying.
args.set_errorHandled(true);
// go to the top so they can see the error message.
window.scroll(0, 0);
}
}
Note that the lblMessage label control needs to be inside the UpdatePanel so that it is cleared on the next PostBack.
So now when I get an exception it displays the real error to the user in a label with red text, something like below.
And the details are logged in my exceptions table.

Much better than the default.