Otrzymywanie „Żądanie JSON było zbyt duże, aby można je było zdezrializować”

203

Otrzymuję ten błąd:

Żądanie JSON było zbyt duże, aby można je było zdezrializować.

Oto scenariusz, w którym ma to miejsce. Mam klasę kraju, który posiada listę portów wysyłkowych tego kraju

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

Korzystam z KnockoutJS po stronie klienta, aby upuszczać kaskadowo. Mamy więc zestaw dwóch list rozwijanych, przy czym pierwszy to kraj, a drugi to porty tego kraju.

Do tej pory wszystko działa dobrze, to mój skrypt po stronie klienta:

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

Problem pojawia się, gdy wybierany jest kraj taki jak Chiny, który ma wiele portów. Więc jeśli masz 3 lub 4 razy „Chiny” w swojej tablicy i chcę wysłać je na serwer, aby zapisać. Wystąpił błąd.

Co powinienem zrobić, aby temu zaradzić?

Kayvan Karim
źródło
4
Dla każdego, kto jest ciekawy, dlaczego tak się dzieje, lub pisania serializatora dla klientów - spójrz na kod źródłowy JsonValueProviderFactory.cs - wygląda na to, że zespół ASP.NET MVC celowo
narzucił

Odpowiedzi:

401

Aby rozwiązać problem, musisz dostosować właściwość maxJsonLength do wyższej wartości web.config.

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

Ustaw wyższą wartość aspnet:MaxJsonDeserializerMembersw ustawieniach aplikacji:

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

Jeśli te opcje nie działają, możesz spróbować utworzyć niestandardową fabrykę dostawców wartości json przy użyciu JSON.NET, jak określono w tym wątku .

VJAI
źródło
57
Pracowałem nad aplikacją MVC4, która serializowała dużą ilość (1k +) obiektów json do kontrolera. Metoda system.web.extensions nic nie zrobiła, ale appSettings to magiczna poprawka. Dzięki!
TNCodeMonkey
4
aspnet:MaxJsonDeserializerMembersteż dla mnie pracował. Czy ktoś wie, gdzie to jest faktycznie udokumentowane?
Matt Burland,
1
Łącze MSDN jest zepsute. Prawidłowy link to msdn.microsoft.com/en-us/library/…
Ido Ran
14
To zadziałało dla mnie, ale właśnie to odkryłem: support.microsoft.com/kb/2661403 ... Zwiększenie tej wartości powyżej ustawienia domyślnego zwiększa podatność serwera na podatność na atak typu „odmowa usługi” opisaną w biuletynie zabezpieczeń MS11- 100
Hero
4
Domyślna wartość aspnet: MaxJsonDeserializerMembers wydaje się wynosić 1000: msdn.microsoft.com/en-us/library/hh975440.aspx .
CRice,
2

Jeśli nie chcesz zmieniać ustawienia globalnego w konfiguracji internetowej

Użycie ustawienia globalnego aktywuje duże odpowiedzi JSON w całej aplikacji, co może doprowadzić do ataku typu „odmowa usługi”.

Jeśli dozwolonych jest kilka lokalizacji wyboru, możesz bardzo szybko użyć innego serializatora json, używając metody Content w następujący sposób:

using Newtonsoft.Json;

// ...

public ActionResult BigOldJsonResponse() 
{
    var response = ServiceWhichProducesLargeObject();
    return Content(JsonConvert.SerializeObject(response));
}
// ...
Gburton
źródło