Use jQuery to catch and display ASP.NET AJAX service errors
AJAX, ASP.NET, UI, jQuery By Dave Ward on March 4th, 2009
If you don’t properly handle the inevitable errors in your web applications, you can expect your users to eventually react about like this guy. Since they typically squelch any server-side errors, AJAX service calls are especially problematic. In fact, they rarely even throw a client-side error when they fail.
Even when a client-side error is thrown, most users won’t notice it and the ones who do notice won’t know what the error means or what to do next. In fact, I’ve found that even many developers don’t notice client-side scripting errors that occur while they’re debugging their own applications!
To help you remedy this problem in your own applications, I want to show you one way that I handle AJAX service call errors with jQuery. To do this, we will build an error-prone web service, make an AJAX request to it via jQuery, handle the resulting server-side errors gracefully, and use a jQuery plugin to attractively present those errors.
Building an erroneous method
To experiment with error handling, the first thing we’ll need is an error. We could use throw() to raise a synthetic error, but let’s build a page method that’s apt to throw a couple of real errors:
[WebMethod] public static int DivideByZero(int Dividend) { // To fool the compiler into not saving us from ourselves. int zero = 0; return (Dividend / zero); }
If this method is called with a parameter that cannot be parsed as an integer, it will throw a type conversion error. If we do correctly call it with a string that can be converted to an integer, we’ll get a division by zero exception.
Using jQuery to call the page method
To interface with the page method, we’ll need an input field to supply the dividend and a button to trigger a call to the page method. Something like this:
<html> <head> <title>Division by Zero Utility v1.0</title> <script type="text/javascript" src="jquery-1.3.2.min.js"></script> <script type="text/javascript" src="default.js"></script> </head> <body> <input type="text" id="Dividend" /> <input type="button" id="Divide" value="Divide by 0" /> </body> </html>
Using jQuery to call an ASP.NET AJAX page method is easy once you understand the required syntax and a few quirks. In default.js, we can use jQuery’s click() to wire our DivideByZero method up to the input button’s click event:
/// <reference path="~/jquery-1.3.2-vsdoc.js /> // When the page loads... $(document).ready(function() { // ...attach an onclick handler to the Divide button. $("#Divide").click(function() { // Trigger a request to the page method. $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", dataType: "json", url: "Default.aspx/DivideByZero", // Supply the Dividend value from our input field. data: "{ 'Dividend': '" + $("#Dividend").val() + "' }", // Error! error: function(xhr, status, error) { // Display a generic error for now. alert("AJAX Error!"); } }); }); });
Notice the error callback function. This function will be raised in the event of any error or timeout when calling the service. For now, we’ll just display an alert() with a static error message.
If you were to run this example now, typing anything in the input field and hitting the “Divide by 0” button will result in the error handler being called. That’s better than nothing, but wouldn’t it be more useful to display specific information about the exception that occurred?
Inspecting the server’s response in Firebug
To improve the detail of our message, we need to dissect the error returned by the server and find where the specific detail lies. To accomplish this most effectively, I recommend using the Firebug addon to Firefox.
Using Firebug to set a breakpoint on the error handler, we’re able to inspect the request’s state at that point and quickly drill down to the information we’re after:

While the status of “error” may seem unhelpful, it is a useful bit of information in some cases. In a more sophisticated error handling scenario, it would allow us to distinguish between a server-side error and a timeout.
However, the undefined error parameter certainly is not helpful.
To find the detail that we need, we’ll have to explore a bit further. Our request’s XMLHttpRequest instance should contain what we’re looking for. Clicking on the green XMLHttpRequest text will shift the Firebug window to inspect that specific object in detail:

Now we’re getting there: The XMLHttpRequest’s responseText property contains a JSON object with all the detail that the server returned.
As you can see in the Firebug screenshot, the Message variable contains a more familiar .NET error. In this case, indicating that the empty string I submitted was unsuitable for conversion to the Int32 parameter that DivideByZero expects.
Making effective use of the error data
As a string, this JSON object isn’t quite what we need. The last thing we should do is try to parse the error message ourselves. While technically possible, it would be messy and prone to breakage, or require using an extra library such as json2.js.
One of the nice things about JSON is that it is a native JavaScript construct. Thus, JavaScript’s eval() will evaluate a JSON string and return an actual JSON object.
To take advantage of that, we can modify the error handler like this:
error: function(xhr, status, error) { // Boil the ASP.NET AJAX error down to JSON. var err = eval("(" + xhr.responseText + ")"); // Display the specific error raised by the server (e.g. not a // valid value for Int32, or attempted to divide by zero). alert(err.Message); }
Now, the properties of the error that we got a glimpse of in Firebug are available via the same dot-notation that you’d expect from any object. In particular, the errors returned by ASP.NET AJAX provide three variables in their JSON response: ExceptionType, Message, and StackTrace.
Note: I would normally recommend against using eval() to evaluate a JSON string. However, it is relatively safe in this case since these messages come directly from the .NET framework and do not contain any user-injected content.
Presenting the error message with jQuery
I’ve written about Mike Alsup’s BlockUI plugin before, showing you how to use it to display modal progress indication and confirmation windows. An often overlooked feature of the plugin is the ability to display basic “growl” style notifications.
See the demo at the bottom of this page for an example of that.
After adding a script reference to blockUI.js, displaying the error “growl” couldn’t be easier:
error: function(xhr, status, error) { var err = eval("(" + xhr.responseText + ")"); // Display the error "growl", with a title of "Error", // the error message as content, and a 20s display time. $.growlUI('Error', err.Message, 20000); }, success: function() { // On the outside chance that our method manages to succeed, // clear any lingering error "growls". $.unblockUI(); }
Since it’s important that the user notice the error message, we can specify a much longer than default timeout for the “growl”. Twenty seconds in the example above.
The success handler is added to make sure any leftover error is cleared after a successful request completes. This avoids any confusion that would be caused by an error message remaining even after a successful request completes.
Because $.growlUI() is just a shortcut for a complex BlockUI usage, $.unblockUI() works on “growl” messages just as if they were $.blockUI() modals.
Note: As with the rest of BlockUI, these “growl” messages can be customized via CSS. For this simple demo, I’m happy with the default styling, but you can easily change it to match your application.
Conclusion
You should never assume your service calls are 100% reliable. This seems obvious, but I’ve encountered mountains of production code without error handling.
As you’ve hopefully seen in this post, it is trivially easy to add great looking error handling to your jQuery service calls. After all is said and done, you’re only looking at about 3-5 extra lines of code. This substantial improvement in usability is well worth the minimal effort.
We focused on an example of using a page method here, but keep in mind that this technique can be implemented to work with both page methods and web service calls.
Source
Possibly related posts
What do you think? Your comments are welcome.
I appreciate all of your comments, questions, and other feedback, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this comment" link underneath the comment you're replying to.
7 Mentions Elsewhere
- DotNetShoutout
- Use jQuery to catch and display ASP.NET AJAX service errors | Encosia - DotNetBurner
- Bruno Campagnolo de Paula weblog » Resumo do dia para 2009-03-04
- Reflective Perspective - Chris Alcock » The Morning Brew #300
- Mar-19-2009 javascript/ajax links | w3feeds
- JQuery Articles
- Use jQuery to catch and display MR AJAX errors « Chorn Sokun’s Weblog


Thank you, Dave! Helpful, as usually. Even having all things known, I must say that you presented them in a very simple and natural combination – just take and use.
Great article! Very simple yet highly effective!
Hi Dave,
I’ve been following your blog for a long while and I really appreciate the quality of your posts.
I have to disagree with this one though; do you think that showing the stack trace error to the user is good in terms of user experience? Don’t you think that the average user will freak out when he sees such a detailed technical error even if you make it look very nice? (Putting lipstick on a pig…)
Maybe it’d be better just to show that an internal error occurred and spare the details to the end user.
Besides, if you think about security guidelines, showing internal error details to the public is not a good practice
Hope this helps,
Javier
One note, this isn’t displaying the stack trace to the user. Just the “Message” (e.g. Attempted to divide by zero).
I definitely agree with you overall. The main purpose here was more to dig into the error content and explain how to make use of that data that comes back from the server. With that, you can present it in any number of ways.
In practice, I’d say a switch() statement to translate expected errors to user-friendly messages would be a good way to go. If I get a chance later, I may amend the post with a section about improving that aspect.
At the same time, what happens if we only think to explicitly handle DivideByZeroException and then the user types a string with an apostrophe in it? I think it’s preferable* to display the “Invalid JSON Primitive” error than do nothing at all.
* Of course, it would be more preferable to write code that an apostrophe doesn’t break, but it’s applicable in this simple example.
That picture is perfect. It sums up about 15% of the last 12 years of my life. :)
Hi Dave,
You’re damm right about the stack, my mistake, I had to go and I couldn’t read the post as through as I’d have liked.
In my opinion all the errors should be shown as something similar to “Internal error. Please contact your admin”. Is a sql connection error an expected exception? Even if it’s not expected, do you still want to show the techy error message related to that? The details should be kept at home in your logging repository.
For the sample of the Json string I have mixed feelings though. I still think that “Invalid Json primitive” is not appropriate for showing purposes but on the other hand, for errors happening in client-side you have no logging support, so a browser screenshot with the specific error could come in very handy to figure out how to fix bugs, especially when an app is already in production.
Why don’t you use a try catch statement in your web method?
When an error occurs, your catch statement could return a status as well as the error message which you would read in JavaScript.
If Status=0 (for example) it means no error occured otherwise you display the error message returns by the web method. It’s what I do and it works fine. It also makes sense to catch the error on the server side as it occurs there (+you can log it in your database if needs be).
With you method, only the end-user is notified of the problem.
The danger there is that you’re assuming that you can anticipate and handle every error that the user will encounter.
If I wrap the DivZero in a try/catch and return a status code for failures, what happens if the user submits a value that can’t be converted to Int32 or a value that throws an “Invalid JSON Primitive” error? Without client-side error handling, the user wouldn’t receive any notification about what happened.
I definitely agree that you should also log errors on the server-side. If you’re relying on your end-users to report errors to you, you probably won’t know about the majority of errors that occur.
The post is good, but I think that you should mention native MS AJAX error handling methods too. They are supereasy to use…
this method of errorhandling works great for me when the Webservice throws the error. However if I simulate a “missing page” scenerio the eval() javascript statement does not compile, and the page progresses like nothing happened.
Replace:
url: “Default.aspx/DivideByZero”,
With:
url: “Nopage.aspx/DivideByZero”,
How do you catch this error?
Hi Dave,
thanks for your article!
but ,why the error function can not be invoked ?
could you help me !
my english is a little poor!
Hello :)
Thanks for article. Rellay good, but I just have a little question
When sending a bad request to the WebService, which creates a error, it returns a “500 Internal Error”
How would you handle this request?
I know your handling it on the client side but should you do something with it on the code behind?
Dave, nice to see this written up. I’ve long cursed the way that jQuery returns error information because there are a number of things that you have to check for.
I think you need a bit more than what you have here though – if there are HTTP level errors you need to possibly manage status codes in addition to an actual error message that the server returns. Casper’s response points at this although I don’t think there’s really any good solution to a 500 level error.
The error handler I use in an $.ajax() wrapper class looks something like this:
error: function(xhr, status) {
var res = xhr.responseText;
var err = null;
if (res && res.charAt(0) == ‘{‘)
var err = JSON.parseWithDate(res);
if (!err) {
if (xhr.status != 200)
err = new CallbackException(xhr.status + ” ” + xhr.statusText);
else
err = new CallbackException(“Unknown Error Response”);
err.detail = res;
}
else
err = new CallbackException(err); // force error to common format
if (errorHandler)
errorHandler(err, _I, xhr);
}
Like your code i try first to eval the result, but if that fails then looking at the status code and returning the server’s status code usually is more useful. This isn’t going to be helpful on most 500 type errors, but it will be if you have a 40x error for missing or unauthorized content at least.
Not sure if you noticed, but at the bottom of the BlockUI plugin page is a link to another plugin called jGrowl. The nice thing about it is that it has stackable growls in case you have multiple notifications or a click-happy user.
http://stanlemon.net/projects/jgrowl.html
I had the same problem. When the exception comes from an Interval Server Error (500), the StackTrace page is shown. I ended up with two solutions. I could either change the Application_Error or get the error through javascript somewhere in the error page. So i decided to go for the second one. By doing this i don’t mess up with the Global.asax.
error: function(result, textStatus, thrownError){
result.responseText.match(/(.*)/i);
MostraCaixa(“AVISO DE ERRO”, error[1] || result.responseText, Botoes.OkAlerta);
$(“.close:visible”).focus();
}
I had the same problem. When the exception comes from an Interval Server Error (500), the StackTrace page is shown. I ended up with two solutions. I could either change the Application_Error or get the error through javascript somewhere in the error page. So i decided to go for the second one. By doing this i don’t mess up with the Global.asax.
error: function(result, textStatus, thrownError){ result.responseText.match(/(.*)/i); MostraCaixa(”AVISO DE ERRO”, error[1] || result.responseText, Botoes.OkAlerta); $(”.close:visible”).focus(); }Hi Dave. Thank you for this awesome post!
I’m running into a problem where I can’t get the exception details when I test a web service from a machine that is not the web server. (machine A has the html page open in a browser that calls a WebService on machine b)
This is what I get:
I tried changing debug to true in web.config, but that didn’t make a difference. Any ideas?
I believe the customErrors setting in your web.config controls that.
Yes, you are correct. Changing customErrors to
fixed it. Thanks!
Indeed, a great post. I’m using it to make ASP.NET MVC ajax calls. But there is a ‘little’ issue. The response text in xhr.responseText is HTML string, not JSON string.
To be honest, this sounds normal for me and when server returns JSON string is strange for me :). Apparently is that, since I’m the only one with this problem, I’m missing something. Do you know what?
Thanks!
You may be receiving HTML string because the error didn’t came from a thrown exception. I noticed that when it is a Internal Server Error (500) it shows the error page defined.
MVC doesn’t return its errors in the same format as ASP.NET AJAX services. That’s normal behavior.
Thanks Dave!