小编典典

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

ajax

我使用ASP.NETMVC从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);

所以显然我会这样称呼:

$('#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和ASP.NET MVC4支持事物的提交方面(在需要扩展ASP.NETMVC来处理提交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" });
}

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


阅读 255

收藏
2020-07-26

共1个答案

小编典典

该问题是由从jQuery 1.8升级到1.9引起的。在jQuery 1.7和1.8中,在MVC中是这样的:

return Json(null);

被接受为有效JSON,并被解释为null。从技术上讲,这将使用HTTP 200将空白字符串发送回客户端,对于jQuery <1.9来说已经足够了。

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

解决方法是在成功的情况下将此消息从服务器传回,而没有其他信息:

return Json(new{});

这通过jQuery的JSON解析器进行了汇总,一切都很好。这也适用:

return Json(true);

更新资料

Musa指出,MVC的这种行为似乎已损坏。这种[独立的堆栈溢出的答案 _使用JSON.NET在ASP.NET MVC 3默认JSON序列化-这可能吗?
涵盖如何使MVC返回null的方法Json(null)-基本上,使用Json.NET而不是ASP.NET
MVC的内置JSON序列化程序。这是我最终使用的解决方案。

您需要使用对该答案的稍作修改的版本才能解决此问题-代码如下。基本上,不要if在传递序列化之前包括检查null 的语句,否则您将陷入同样的​​困境。

更新2

Json.NET中ISO 8601日期的默认实现在尝试使用进行解析时会中断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');

但这会引发异常:

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

Internet Explorer
9的Date()实现只能处理3毫秒的地方,无法解决任何其他问题。要解决此问题,您必须重写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);
    }
}

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

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

2020-07-26