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

Posted

技术标签:

【中文标题】从 ASP.NET MVC 返回 null 时,jQuery post JSON 失败【英文标题】:jQuery post JSON fails when returning null from ASP.NET MVC 【发布时间】:2013-04-03 03:02:02 【问题描述】:

我使用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);

所以很明显我会这样称呼它:

$('#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 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" );

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

【问题讨论】:

顺便说一句,exception.message 中的全局 $(document).ajaxError... 显示:“Unexpected end of input”当 Json(null) 返回时(只是提一下,它没有帮助我来找出问题的原因)。 【参考方案1】:

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

return Json(null);

被接受为有效的 JSON 并被解释为 null。从技术上讲,这会使用 HTTP 200 向客户端发送一个空白字符串,这对于 jQuery

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

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

return Json(new);

通过 jQuery 的 JSON 解析器,一切顺利。这也有效:

return Json(true);

更新

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

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

更新 2

Json.NET 中 ISO 8601 日期的默认实现在尝试使用 new Date(...) 解析它时会破坏 Internet Explorer 9 及以下。换句话说,这些在 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() 实现只能处理三毫秒的位置。要解决此问题,您必须覆盖 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

【讨论】:

return Json(null); 返回一个空字符串听起来很糟糕,它应该返回null @Musa 可能,尽管在这一点上这也可能是一个突破性的变化——我去挖掘了,它似乎从 MVC 的开始就返回了一个空字符串。我确实同意这可能是解决这个问题的更清洁的方法。这个答案涵盖了这样做,尽管示例代码在 Json.Net 可以尝试之前检查 null 并返回空字符串 - 删除这 2 行,您将得到未修改的 null 返回。 ***.com/a/7150912/176877

以上是关于从 ASP.NET MVC 返回 null 时,jQuery post JSON 失败的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ASP.NET MVC 控制器返回 Ajax“失败”?

从 ASP.NET MVC 操作返回部分视图和 JSON

ASP.NET MVC 接收“null”作为字符串而不是 null

ASP.NET Web API将MV响应转换为MVC 4中的json List

ASP.NET MVC 4框架揭秘:从Unity来认识IoC(2)

在 asp.net mvc 中返回错误的最佳实践是啥