11

In MVC, why does returning Content sometimes fail in the Ajax callback, while returning Json works, even for simple string objects?

Even when it fails, the data is still available if you were to access it in the always callback...

Update:

When I set the contentType in the ajax call to text/xml the response will no longer enter the error message.

AJAX:

$.ajax({
    cache: false,
    type: "GET",
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    url: "/MyController/GetFooString",
    data: { },
    success: function (data) {
        alert(data);
    },
    error: function (xhr, ajaxOptions, thrownError) {
        alert("Ajax Failed!!!");
    }
}); // end ajax call

Controller Action That Fails (Sometimes)

Even when it fails, the data is still available.

public ActionResult GetFooString()
{
    String Foo = "This is my foo string.";
    return Content(Foo);
} // end GetFooString

Controller Action That Always Works

public ActionResult GetFooString()
{
    String Foo = "This is my foo string.";
    return Json(Foo, JsonRequestBehavior.AllowGet);
} // end GetFooString
9
  • 2
    Define "fails." What is the actual response returned from the server and how does it differ from a "successful" response? Commented Sep 22, 2014 at 20:24
  • It enters the error function in the Ajax method even though the data is returned correctly, and without any errors. Successful response is triggered in the Ajax Success method, where I alert data. Commented Sep 22, 2014 at 20:27
  • Try adding contentType: "application/json", to your parameters list. Commented Sep 22, 2014 at 20:29
  • @silencedmessage: In order for there to be any difference in the handler, something about the response must be different. Its content, its headers, something. Commented Sep 22, 2014 at 20:34
  • @David Returning content doesn't fail if I change the content-type to text/xml in the Ajax call. A coworker had a theory that Content returns a string object that is translated as plain text, whereas returning json explicitly returns a json object. Commented Sep 22, 2014 at 20:47

1 Answer 1

16

Using Content(Foo); sends a response that doesn't have the mime type header. This happens because you're not setting ContentType when using this overload. When the Content-Type is not set, jQuery will try to guess the content type. When that happens, whether it can successfully guess or not depends on the actual content and underlying browser. See here:

dataType (default: Intelligent Guess (xml, json, script, or html))

Json(...) on the other hand explicitly sets the content type to "application/json" so jQuery knows exactly what to treat the content as.

You can get consistent result from Content if you use the 2nd overload and specify a ContentType:

return Content(Foo, "application/json"); // or "application/xml" if you're sending XML

But if you're always dealing with JSON, then prefer using JsonResult

return Json(Foo, JsonRequestBehavior.AllowGet); 
Sign up to request clarification or add additional context in comments.

3 Comments

+1. But if the OP will always expect JSON, wouldn't be better to just change ActionResult to JsonResult?
@MelanciaUK: If one always expects JSON, then yes. But I see your point. Updating my answer...
In this case, I would always be expecting JSON, but the part that I was truly missing was the mime type and the differences between ContentResult and JsonResult.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.