Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Just posting this here in case others run into this.

I use ASP.Net MVC to post JSON from jQuery, and get some JSON back, using this little library function:

(function($) {
    $.postJson = function(url, data) {
        return $.ajax({
            url: url,

            data: JSON.stringify(data),
            type: 'POST',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8'
        });
    };
})(jQuery);

So obviously I'll call this like:

$('#button').click(function() {
    $.postJson('/controller/action', { Prop1: 'hi', Prop2: 'bye' })
    .done(function(r) { alert('It worked.'); })
    .fail(function(x) { alert('Fail! ' + x.status); });
});

MVC3 and MVC4 support the submit side of things (before that you needed to extend MVC to handle submitting JSON), but the problem I'm running into is on the return. On the Controller I often return null to basically say "Success, nothing else to say," like:

[HttpPost]
public JsonResult DoSomething(string Prop1, string Prop2)
{
    if (doSomething(Prop1, Prop2)
        return Json(null); // Success

    return Json(new { Message = "It didn't work for the following reasons" });
}

I use this pattern frequently and it works fine - my success/done callback gets called and all is well. But recently I upgraded MVC and jQuery and it's stopped working - instead my fail callback is getting called whenever I return Json(null);. Furthermore, I've inspected the response and the statusCode getting returned is in fact 200, so the server isn't failing - jQuery's just saying it is.

share|improve this question
BTW the global $(document).ajaxError... shows in exception.message: "Unexpected end of input" when Json(null) is returned (just to mention it, it didn't help me to find the reason for the problem). – Slauma Jun 3 at 16:18

1 Answer

up vote 2 down vote accepted

The problem was caused by upgrading from jQuery 1.8 to 1.9. In jQuery 1.7 and 1.8, this in MVC:

return Json(null);

was accepted as valid JSON and interpreted as null. Technically this sends a blank string back to the client with HTTP 200, and that's good enough for jQuery <1.9.

But now (we're using jQuery 1.9.1), it attempts to parse the empty string as JSON, jQuery's JSON parser throws an exception on empty string, and that triggers a code chain that ends in a fail() callback instead.

A workaround is to instead pass this back from the server on success with no other info:

return Json(new{});

That passes muster with jQuery's JSON parser and all is well. This also works:

return Json(true);


Update

Musa notes below this behavior by MVC seems broken. This separate StackOverflow answer covers how to get MVC to return null for Json(null) - basically, use Json.Net instead of MVC's built-in Json serializer. This is the solution I ultimately ended up using.

Using JSON.net as default JSON serializer in ASP.NET MVC 3 - Is it possible?

You need to use a slightly modified version of that answer to fix this however - code below. Basically, don't include the if statement checking for null before passing to serialize, or you're right back in the same predicament.


Update 2

The default implementation of ISO 8601 Dates in Json.Net breaks IE9 and below when it attempts to parse it with new Date(...). To fix this you have to override the Json.Net date format to force 3 millisecond places in the output. Included in the code below.

public class JsonNetResult : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var response = context.HttpContext.Response;

        response.ContentType = !String.IsNullOrEmpty(ContentType) ? ContentType : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        var settings = new JsonSerializerSettings
        {
            Converters = new[] {new IsoDateTimeConverter
            {
                DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffK"
            }}
        };
        var jsonSerializer = JsonSerializer.Create(settings);

        jsonSerializer.Serialize(response.Output, Data);
    }
}
share|improve this answer
return Json(null); returning an empty string sounds broken, it should return null – Musa Apr 11 at 3:18
@Musa Probably, although at this point that might also be a breaking change - I went digging and it appears it has returned an empty string for null since the beginning days of MVC. I do agree that might be a cleaner solution to this problem though. This answer covers doing so, although the sample code checks for null and returns empty string before Json.Net can get a shot at it - remove those 2 lines and you'll get null returned unmodified. stackoverflow.com/a/7150912/176877 – Chris Moschini Apr 11 at 3:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.