Gracefully handling errors that occur during Ajax calls in a simple yet standard way that didn’t clutter up my methods with a lot of extra code took a while to figure out.
I ended up creating an OnException action filter that I place on my controller or methods as appropriate. When an error is thrown in a method or controller that is decorated with the attribute, execution goes to the filter. Generally I try and throw custom exceptions with an appropriate message. If the request was made via Ajax, the code in the filter below creates a JsonResult with a message to be sent back to the client.
Code Snippet
- using System;
- using System.Net;
- using System.Web.Mvc;
-
- namespace Website.ActionFilters
- {
- [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
- public class AjaxException : ActionFilterAttribute, IExceptionFilter
- {
- public void OnException(ExceptionContext filterContext)
- {
- if (!filterContext.HttpContext.Request.IsAjaxRequest()) return;
-
- filterContext.Result = AjaxError(filterContext.Exception.Message, filterContext);
-
- //Let the system know that the exception has been handled
- filterContext.ExceptionHandled = true;
- }
-
- protected JsonResult AjaxError(string message, ExceptionContext filterContext)
- {
- //If message is null or empty, then fill with generic message
- if (String.IsNullOrEmpty(message))
- message = "Something went wrong while processing your request. Please refresh the page and try again.";
-
- //Set the response status code to 500
- filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
-
- //Needed for IIS7.0
- filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
-
- return new JsonResult
- {
- Data = new{ ErrorMessage = message },
- ContentEncoding = System.Text.Encoding.UTF8,
- JsonRequestBehavior = JsonRequestBehavior.DenyGet
- };
- }
- }
- }
On the client side, I then have a jQuery $.ajaxSetup method that sets how all jQuery Ajax calls handle their errors.
Code Snippet
- //Set defaults for all of the ajax calls
- $.ajaxSetup({
- type: "POST",
- cache: false,
- error: function(request) {
- //code to display message to user
- }
- });
This seems to have worked out pretty well for me. Would you do anything different?