Patrick Desjardins Blog
Patrick Desjardins picture from a conference

Returning a JsonResult within the Error function of JQuery Ajax

Posted on: 2012-04-04

Let say that you have an exception on the server side and you want to specify this error to the client, what could you do?

The easiest way is to return the error into the return value directly:

public JsonResult Create(MyObject myObject) { 
  //AllFine 
  return Json(new { IsCreated = True, Content = ViewGenerator(myObject)); 
  //Error 
  return Json(new { IsCreated = false, Content = ViewGenerator(myObject), ErrorMessage = 'Could not save because XYZ'); 
} 

In the Javascript, we just need to take the error message and display it.

$.ajax({ 
  type: "POST", 
  dataType: "json", 
  url: "MyObjectController/Create", 
  data: JSON.stringify(myObjectJson), 
  success: function (result) { 
    if(result.IsCreated) { 
      //... 
    } else { 
      alert(result.ErrorMessage); 
    } 
  } 
}); 

This is a correct way to do it. But sometime, you may want to return handled error this way because you "control" the situation and do something else for unhandled error. This could be the case of any error that you do not catch with precision but you still need to return something to the client. Since you are using Ajax you may not want to redirect your user to another page but just to display an alert that the operation is unsuccessful.

This can be done by changing the Response Header with a Http Code that is different from the normal 200.

 public JsonResult Create(MyObject myObject) { 
   //AllFine 
   return Json(new { IsCreated = True, Content = ViewGenerator(myObject));

  //Use input may be wrong but nothing crashed 
  return Json(new { IsCreated = False, Content = ViewGenerator(myObject)); 

  //Error 
  Response.StatusCode = (int)HttpStatusCode.InternalServerError; 
  return Json(new { IsCreated = false, Content = ViewGenerator(myObject), ErrorMessage = 'Could not save because XYZ'); 
} 

The Javascript can than go in three different direction:

$.ajax({ 
  type: "POST", 
  dataType: "json", 
  url: "MyObjectController/Create", 
  data: JSON.stringify(myObjectJson), 
  success: function (result) { 
    if(result.IsCreated) { 
      //... ALL FINE 
    } else { 
      //... Use input may be wrong but nothing crashed 
    } 
  }, error: function (jqXHR, textStatus, errorThrown) { 
    alert("Error:" + jQuery.parseJSON(jqXHR.responseText).Info); //Error
  } 
}); 

This way, you handle in a clear way how to display error to the user or to display problem with his inputs. It also give you the possibility to do it in a clean way at the server side and also to the client side.

For you curiosity, if you want to play with different status you can go see in System.Net the enumeration HttpStatusCode all different possible values.

Here is it:

namespace System.Net { 
  public enum HttpStatusCode { 
    Continue = 100, SwitchingProtocols = 101, OK = 200, Created = 201, Accepted = 202, NonAuthoritativeInformation = 203, NoContent = 204, ResetContent = 205, PartialContent = 206, Ambiguous = 300, MultipleChoices = 300, Moved = 301, MovedPermanently = 301, Found = 302, Redirect = 302, RedirectMethod = 303, SeeOther = 303, NotModified = 304, UseProxy = 305, Unused = 306, RedirectKeepVerb = 307, TemporaryRedirect = 307, BadRequest = 400, Unauthorized = 401, PaymentRequired = 402, Forbidden = 403, NotFound = 404, MethodNotAllowed = 405, NotAcceptable = 406, ProxyAuthenticationRequired = 407, RequestTimeout = 408, Conflict = 409, Gone = 410, LengthRequired = 411, PreconditionFailed = 412, RequestEntityTooLarge = 413, RequestUriTooLong = 414, UnsupportedMediaType = 415, RequestedRangeNotSatisfiable = 416, ExpectationFailed = 417, InternalServerError = 500, NotImplemented = 501, BadGateway = 502, ServiceUnavailable = 503, GatewayTimeout = 504, HttpVersionNotSupported = 505, 
  } 
}