When coding up Ajax calls in ASP.Net MVC we have a lot of options as far as issuing calls, handling them on the server, and dealing with successes and failures on the client. Some things clearly have a correct answer, but I've been unable to find clear-cut guidance. So, end-to-end, what is the correct way to make an ajax call?
Including
Any other things people have strong opinions on?
What is the best way to inject the URL of the action for the URL into the Ajax call?
There's no convention about this and it also largely depends how your content has been brought to the client. Was it via views/partial views (in which case you could generate URLs with Html
/Url
helper methods or is it purely generated on the client (templating and such). It's quite common that we just want some usual HTML elements to extend with Ajax behaviour (like forms, buttons and links). In this situation it's best to provide correct URLs that we can also read from them and use them in our scripts (like href
in links). It's also more clear to users where things are pointing to. Whether we convert them to GET/POST/DELETE/PUT requests doesn't really matter any more. I would suggest to avoid hard-coding URLs in your scripts because you may change routing or provide other means of processing. By using Html
helpers wherever possible is a much better way in terms of maintenance. When adding URLs to elements that don't support them automatically (no href
or src
attribute) you can always add them as custom attributes especially when you use data attribute (like data-href
or similar). Read John Resig's blog post about these.
What are the considerations when choosing JsonBehavior?
It's best to make POST requests when you have to return Json. In GET requests you have to be aware of the possible implications JSON Hijacking that's also the reason why you have to explicitly specify that you allow get requests with JSON results.
What is the best way to handle errors on the server side?
The best way to process server errors (that can't and shouldn't be suppressed) is to actually inform the user of the error. Details of it are usually not important since users are not development savvy but telling them something went wrong is ok. Especially if you can offer them some sort of a solution. And with Ajax call it's bets to return errors as errors that can be handled with error handler Javascript functions. I've written a blog post that details the whole process and also provides the code that shows how to correctly handle validation errors. I personally think that returning errors as success is wrong. hence I don't. But that's argumentative. My controller actions are rather simplified by the code I use:
[HandleModelStateException]
public ActionResult AddUser(User user)
{
if (!this.ModelState.IsValid)
{
throw new ModelStateException(this.ModelState);
}
// process valid data
}
Should the client side error() callback be triggered by any errors (ie unexpected OutOfMemoryException
), or only by foreseeable errors (ie invalid input)?
As stated previously errors should be reported to users when they will get unexpected results from what they initiated. Don't suppress errors that should be reported to them. But don't go into too much detail. Out of memory exception is a bit too complex to explain tu usual computer users. Report something human friendly and short.
What is the best way of exporting errors in a way that the error()
callback will be triggered.
Look at my blog post and check the code to see how to create errors that are handled by the error()
function
Best way of ensuring the error callback gets the correct status code and response text.
Same blog post
Should validation errors result in an error StatusCode
or should they be part of a responding validation object.
Validation errors are actually warnings by nature and should be treated as such. That's why you can see positive form validation pattern on some sites that also report when data is valid instead of just informing users that they've made yet another mistake. Validation errors are usually rooted in invalid user interface experience and insufficient information.
What is the best way to handle errors on the client side?
This largely depends on your application but I suggest you follow proven patterns because users are likely to know the drill and won't confuse them. Why do you think OpenOffice uses almost identical UI as Microsoft Office? Because users know how it works so it's more likely to be acquainted with the app fast and painlessly. But if you can, don't treat users as dumb people. Use positive validation. Some errors should also be displayed as errors. Oh. Btw. I use unobtrusive infos in my app where information such as successful operation is reported to users but doesn't intrude their work. It automatically disappears after a while. Similar to what GMail does. It just informs you that mail has been sent and this info doesn't need any confirmation.
jQuery ajax()
functin supports success and error functions, so it's wise to use both. Again: Returning errors as success is not right. We wouldn't need error functions than at all. My HandleModelState action filter returns errors with particular 400 error code that can be used and its result as well.
$.ajax({
url: $(this).attr("href"),
data: someDataObj,
type: "POST",
success: function(data){
// process data
},
error: function(xhr, status, err){
if (xhr.status = 400) {
// handle my error in xhr.resposeText
}
else {
// handle other errors that are cause by unknown processing
}
}
});
Should unexpected errors server-side be displayed in a similar way as the validation summary? Maybe a just "something-went-wrong" dialog? Should the client be able to distinguish between the two?
People don't like the big red alerts. If something is a warning by nature it should be treated friendlier than actual errors that prevent your app to work properly. Validation in particular should be very friendly. Errors should be confirmed by users, warnings maybe shouldn't. Depends on their nature. But if they should be then they're probably errors.
I hope this clears some things for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With