228

I'm getting this Error:

The JSON request was too large to be deserialized.

Here's a scenario where this occurs. I have a class of country which hold a list of shipping ports of that country

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

I use KnockoutJS on the client side to make a cascading drop downs. So we have an array of two drop downs, where the first one is country, and the second one is ports of that country.

Everything is working fine so far, this my client side script:

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

The problem occurs when a country like China is selected, which has lots of ports. So if you have 3 or 4 times "China" in your array and I want to send it to the server to save. The error occurs.

What should I do to remedy this?

Jeroen
  • 60,696
  • 40
  • 206
  • 339
Kayvan Karim
  • 2,986
  • 2
  • 18
  • 18
  • 4
    For anybody curious why this happens or writing their customer serializer - take a look at [source code of JsonValueProviderFactory.cs](https://github.com/mono/aspnetwebstack/blob/master/src/System.Web.Mvc/JsonValueProviderFactory.cs#L118) - seems like ASP.NET MVC team intentionally put limit at 1000. – nikib3ro Apr 07 '15 at 04:42

3 Answers3

442

You have to adjust the maxJsonLength property to a higher value in web.config to resolve the issue.

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

Set a higher value for aspnet:MaxJsonDeserializerMembers in the appSettings:

<appSettings>
  <add key="aspnet:MaxJsonDeserializerMembers" value="150000" />
</appSettings>

If those options are not working you could try creating a custom json value provider factory using JSON.NET as specified in this thread.

Community
  • 1
  • 1
VJAI
  • 32,167
  • 23
  • 102
  • 164
  • 57
    I was working on a MVC4 application that was serializing a large volume (1k+) of json objects to a controller. The system.web.extensions method didn't do anything, but the appSettings was the magic fix. Thanks! – DeeDub Oct 17 '12 at 20:59
  • 4
    `aspnet:MaxJsonDeserializerMembers` worked for me too. Does anybody know where this is actually documented? – Matt Burland Apr 08 '13 at 18:40
  • 1
    The MSDN link is broken. The correct link is http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.maxjsonlength.aspx – Ido Ran May 28 '13 at 09:42
  • 17
    It worked for me, but just found out this: http://support.microsoft.com/kb/2661403 ... Increasing this value above the default setting increases the susceptibility of your server to the Denial of Service vulnerability that is discussed in security bulletin MS11-100. – Hero Aug 23 '13 at 13:25
  • 4
    The default value of aspnet:MaxJsonDeserializerMembers seems to be 1000 : http://msdn.microsoft.com/en-us/library/hh975440.aspx. – CRice Sep 11 '14 at 23:07
  • The appSettings did it for me in ASP.NET MVC 5. The jsonSerialization didn't work. – Loudenvier Jun 26 '15 at 06:50
  • this worked for me – Muhammad Sohail Jul 30 '15 at 12:24
  • As I understand it, the reason for the `appSetting` instead of `system.web.extensions` setting (e.g. `jsonSerialization`) is that this security limit caps the _number of items in the request_ before ASP.NET deserializes it. This does not affect any serializer limit on _number of members in the object_ after ASP.NET decides to deserialize it. – Suncat2000 Jul 13 '17 at 15:35
  • This takes a int, so the max value is 2147483647 – Lord Darth Vader Jan 24 '18 at 10:22
  • A Ton of Smile :) – Chandan Kumar Feb 06 '19 at 04:48
2

If you don't want to change a global setting in the web config

Using a global setting will activate large json responses throughout your entire application which might open you up to a denial of service attack.

If a few choice locations are allowed this, you can very quickly use another json serialiser using the Content method like so:

using Newtonsoft.Json;

// ...

public ActionResult BigOldJsonResponse() 
{
    var response = ServiceWhichProducesLargeObject();
    return Content(JsonConvert.SerializeObject(response));
}
// ...
speciesUnknown
  • 1,644
  • 2
  • 14
  • 27
0

Setting doesn't always work. The best way to handle this is through the controller, You would have to write your own Serialize JSON method. This is how I solved returning a very large json serialized object as a response to a jquery .Ajax call.

C#: replace the JsonResult data type with ContentResult

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

Then in Web.config file increase to maximum size

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

That work for me.