从 ASP.NET MVC 返回 null 时,jQuery post JSON 失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15939944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 16:04:17  来源:igfitidea点击:

jQuery post JSON fails when returning null from ASP.NET MVC

jqueryajaxasp.net-mvcjsonnull

提问by Chris Moschini

I use ASP.NET MVCto post JSON from jQuery, and get some JSON back, using this little library function:

我使用ASP.NET MVC从 jQuery 发布 JSON,并使用这个小库函数返回一些 JSON:

(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); });
});

ASP.NET MVC 3 and ASP.NET MVC 4 support the submit side of things (before that you needed to extend ASP.NET 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:

ASP.NET MVC 3 和 ASP.NET MVC 4 支持事物的提交端(在此之前您需要扩展 ASP.NET MVC 以处理提交 JSON),但我遇到的问题是返回。在控制器上,我经常返回 null 基本上是说“成功,没什么好说的”,例如:

[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 ASP.NET 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.

我经常使用这种模式并且它工作正常 - 我的成功/完成回调被调用,一切都很好。但是最近我升级了 ASP.NET MVC 和 jQuery,但它停止工作了 - 相反,每当我return Json(null);. 此外,我检查了响应,返回的 statusCode 实际上是 200,所以服务器没有失败 - jQuery 只是说它是。

回答by Chris Moschini

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

问题是由 jQuery 1.8 升级到 1.9 引起的。在 jQuery 1.7 和 1.8 中,这在 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.

被接受为有效的 JSON 并解释为 null。从技术上讲,这会使用 HTTP 200 向客户端发送一个空字符串,这对于 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.

但是现在(我们使用的是 jQuery 1.9.1),它尝试将空字符串解析为 JSON,jQuery 的 JSON 解析器在空字符串上抛出异常,并触发以fail()回调结尾的代码链。

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

一种解决方法是在成功时将其从服务器传回,而没有其他信息:

return Json(new{});

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

这通过了 jQuery 的 JSON 解析器,一切都很好。这也有效:

return Json(true);



Update

更新

Musa notes below this behavior by MVC seems broken. This separate Stack Overflow answer to Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?covers how to get MVC to return null for Json(null)- basically, use Json.NET instead of ASP.NET MVC's built-in JSON serializer. This is the solution I ultimately ended up using.

Musa 在 MVC 的这种行为下面的注释似乎被破坏了。这个单独的 Stack Overflow 回答Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - 可能吗?涵盖了如何让 MVC 返回 null Json(null)- 基本上,使用 Json.NET 而不是 ASP.NET MVC 的内置 JSON 序列化程序。这是我最终使用的解决方案。

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

但是,您需要使用该答案的略微修改版本来解决此问题 - 代码如下。基本上,if在传递到序列化之前不要包含检查 null的语句,否则您又会回到同样的困境。



Update 2

更新 2

The default implementation of ISO 8601 Dates in Json.NET breaks Internet Explorer 9and below when it attempts to parse it with new Date(...). In other words, these parse fine in Internet Explorer 9:

ISO 8601的日期的Json.NET的默认实现突破的Internet Explorer 9及以下时,它试图与解析它new Date(...)。换句话说,这些在 Internet Explorer 9 中解析得很好:

var date = new Date('2014-09-18T17:21:57.669');
var date = new Date('2014-09-18T17:21:57.600');

But this throws an exception:

但这会引发异常:

var date = new Date('2014-09-18T17:21:57.6');

Internet Explorer 9's Date() implementation can't cope with anything but exactly three millisecond places. To fix this you have to override the Json.NET date format to force it. Included in the code below.

Internet Explorer 9 的 Date() 实现只能处理三个毫秒的位置。要解决此问题,您必须覆盖 Json.NET 日期格式以强制使用它。包含在下面的代码中。

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);
    }
}

A Gist that demonstrates how to tie this into a BaseController:

演示如何将其绑定到 BaseController 的 Gist:

https://gist.github.com/b9chris/6991b341e89bb0a4e6d801d02dfd7730

https://gist.github.com/b9chris/6991b341e89bb0a4e6d801d02dfd7730