获取“JSON请求过大无法反序列化”错误信息

228

我遇到了这个错误:

JSON请求过大无法反序列化。

以下是导致此错误的一种情况。我有一个国家类,其中包含该国家的一系列航运港口列表。

public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Port> Ports { get; set; }
}

我在客户端使用KnockoutJS制作级联下拉菜单。因此,我们有一个包含两个下拉菜单的数组,第一个是国家,第二个是该国家的港口。

到目前为止,一切都运行良好,这是我的客户端脚本:

var k1 = k1 || {};
$(document).ready(function () {

    k1.MarketInfoItem = function (removeable) {
        var self = this;
        self.CountryOfLoadingId = ko.observable();
        self.PortOfLoadingId = ko.observable();
        self.CountryOfDestinationId = ko.observable();
        self.PortOfDestinationId = ko.observable();  
    };

    k1.viewModel = function () {
        var marketInfoItems = ko.observableArray([]),
            countries = ko.observableArray([]),

            saveMarketInfo = function () {
                var jsonData = ko.toJSON(marketInfoItems);
                $.ajax({
                    url: 'SaveMarketInfos',
                    type: "POST",
                    data: jsonData,
                    datatype: "json",
                    contentType: "application/json charset=utf-8",
                    success: function (data) {
                        if (data) {
                            window.location.href = "Fin";
                        } else {
                            alert("Can not save your market information now!");
                        }

                    },
                    error: function (data) { alert("Can not save your contacts now!"); }
                });
            },

            loadData = function () {
                $.getJSON('../api/ListService/GetCountriesWithPorts', function (data) {
                    countries(data);
                });
            };
        return {
            MarketInfoItems: marketInfoItems,
            Countries: countries,
            LoadData: loadData,
            SaveMarketInfo: saveMarketInfo,
        };
    } (); 

当选择像中国这样有许多港口的国家时,问题就会出现。因此,如果您的数组中有3或4次“China”,而我想将其发送到服务器保存,则会出现错误。

我该怎么办才能解决这个问题?


4
对于任何好奇为什么会发生这种情况或者正在编写自己的客户端序列化程序的人,请查看 JsonValueProviderFactory.cs 的源代码(https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Mvc/JsonValueProviderFactory.cs#L118),似乎 ASP.NET MVC 团队有意将限制设置为 1000。 - nikib3ro
3个回答

444

您需要在web.config中将 maxJsonLength 属性调整为更高的值以解决此问题。

<system.web.extensions>
    <scripting>
        <webServices>
            <jsonSerialization maxJsonLength="2147483644"/>
        </webServices>
    </scripting>
</system.web.extensions>

在appSettings中将aspnet:MaxJsonDeserializerMembers的值设置得更高:

<appSettings>
  <add key="aspnet:MaxJsonDeserializerMembers" value="150000" />
</appSettings>
如果这些选项不起作用,您可以尝试使用JSON.NET创建自定义的json值提供程序工厂,如此线程中所指定的。

57
我正在开发一个MVC4应用程序,将1k+个Json对象序列化到控制器中。System.web.extensions方法没有起到任何作用,但是appSettings是一个神奇的解决方案。谢谢! - DeeDub
4
aspnet:MaxJsonDeserializerMembers 对我也有效。有人知道这个在哪里可以找到官方文档吗? - Matt Burland
1
MSDN的链接已损坏。正确的链接是http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.maxjsonlength.aspx。 - Ido Ran
17
这对我有效,但刚发现这个:http://support.microsoft.com/kb/2661403
... 将此值增加到默认设置以上会增加服务器受到拒绝服务漏洞的风险,该漏洞在安全公告MS11-100中有讨论。
- Hero
4
aspnet:MaxJsonDeserializerMembers 的默认值似乎是1000:http://msdn.microsoft.com/en-us/library/hh975440.aspx。 - CRice
显示剩余5条评论

2

如果您不想更改Web Config中的全局设置

使用全局设置将在整个应用程序中激活大型JSON响应,这可能会使您面临拒绝服务攻击。

如果只允许在少数几个位置使用此功能,则可以快速使用另一个JSON序列化程序,方法是使用Content方法,如下所示:

Original Answer翻译成"最初的回答"

using Newtonsoft.Json;

// ...

public ActionResult BigOldJsonResponse() 
{
    var response = ServiceWhichProducesLargeObject();
    return Content(JsonConvert.SerializeObject(response));
}
// ...

0

设置并不总是有效。 处理这个问题的最佳方式是通过控制器, 您需要编写自己的Serialize JSON方法。 这就是我解决将非常大的JSON序列化对象作为响应返回给jquery .Ajax调用的方法。

C#: 用ContentResult替换JsonResult数据类型

// GET: Manifest/GetVendorServiceStagingRecords
[HttpGet]
public ContentResult GetVendorServiceStagingRecords(int? customerProfileId, int? locationId, int? vendorId, DateTime? invoiceDate, int? transactionId, int? transactionLineId)
{
    try
    {
        var result = Manifest.GetVendorServiceStagingRecords(customerProfileId, locationId, vendorId, invoiceDate, null, null, transactionId, transactionLineId);
        return SerializeJSON(result);
    }
    catch (Exception ex)
    {
        Log.Error("Could not get the vendor service staging records.", ex);

        throw;
    }
}

private ContentResult  SerializeJSON(object toSerialize)
{
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    serializer.MaxJsonLength = Int32.MaxValue; // Wahtever max length you want here
    var resultData = toSerialize; //Whatever value you are serializing
    ContentResult result = new ContentResult();
    result.Content = serializer.Serialize(resultData);
    result.ContentType = "application/json";
    return result;
}

然后在 Web.config 文件中将大小增加到最大

<system.web.extensions>
  <scripting>
    <webServices>
      <jsonSerialization maxJsonLength="999999999" />
    </webServices>
  </scripting>
</system.web.extensions>

那对我有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接