Obtenir "La requête JSON était trop volumineuse pour être désérialisée"

203

Je reçois cette erreur:

La demande JSON était trop volumineuse pour être désérialisée.

Voici un scénario où cela se produit. J'ai une classe de pays qui détient une liste des ports d'expédition de ce pays

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

J'utilise KnockoutJS du côté client pour faire une liste déroulante en cascade. Nous avons donc un éventail de deux listes déroulantes, la première étant le pays et la seconde les ports de ce pays.

Tout fonctionne bien jusqu'à présent, ce script côté client:

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

Le problème se produit lorsqu'un pays comme la Chine est sélectionné, qui possède de nombreux ports. Donc, si vous avez 3 ou 4 fois "Chine" dans votre baie et que je veux l'envoyer au serveur pour l'enregistrer. L'erreur se produit.

Que dois-je faire pour y remédier?

Kayvan Karim
la source
4
Pour quiconque se demande pourquoi cela se produit ou écrit son sérialiseur client - jetez un œil au code source de JsonValueProviderFactory.cs - il semble que l'équipe ASP.NET MVC ait intentionnellement mis la limite à 1000.
nikib3ro

Réponses:

401

Vous devez ajuster la propriété maxJsonLength à une valeur plus élevée web.configpour résoudre le problème.

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

Définissez une valeur plus élevée pour aspnet:MaxJsonDeserializerMembersdans l'appSettings:

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

Si ces options ne fonctionnent pas, vous pouvez essayer de créer une fabrique de fournisseur de valeur json personnalisée à l'aide de JSON.NET comme spécifié dans ce fil .

VJAI
la source
57
Je travaillais sur une application MVC4 qui sérialisait un grand volume (1k +) d'objets json sur un contrôleur. La méthode system.web.extensions n'a rien fait, mais appSettings était la solution magique. Merci!
TNCodeMonkey
4
aspnet:MaxJsonDeserializerMemberstravaillé pour moi aussi. Quelqu'un sait-il où cela est réellement documenté?
Matt Burland le
1
Le lien MSDN est rompu. Le lien correct est msdn.microsoft.com/en-us/library/…
Ido Ran
14
Cela a fonctionné pour moi, mais je viens de découvrir ceci: support.microsoft.com/kb/2661403 ... L'augmentation de cette valeur au-dessus du paramètre par défaut augmente la vulnérabilité de votre serveur à la vulnérabilité de déni de service décrite dans le bulletin de sécurité MS11- 100.
Hero
4
La valeur par défaut d'aspnet: MaxJsonDeserializerMembers semble être 1000: msdn.microsoft.com/en-us/library/hh975440.aspx .
CRice
2

Si vous ne souhaitez pas modifier un paramètre global dans la configuration Web

L'utilisation d'un paramètre global activera de grandes réponses json dans l'ensemble de votre application, ce qui pourrait vous ouvrir à une attaque par déni de service.

Si quelques emplacements de choix sont autorisés, vous pouvez très rapidement utiliser un autre sérialiseur json en utilisant la méthode Content comme ceci:

using Newtonsoft.Json;

// ...

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