7

Можно ли установить неограниченную длину для maxJsonLength в web.config?

1

Я использую функцию автозаполнения jQuery. Когда я пытаюсь получить список из более чем 17000 записей (каждая из которых не превышает 10 символов в длину), происходит превышение длины, и возникает ошибка:

Exception information: 
Exception type: InvalidOperationException 
Exception message: Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.

Могу ли я установить неограниченную длину для свойства maxJsonLength в файле web.config? Если нет, какова максимальная длина, которую я могу установить?

5 ответ(ов)

3

В MVC 4 вы можете переопределить метод Json в вашем контроллере следующим образом:

protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
{
    return new JsonResult()
    {
        Data = data,
        ContentType = contentType,
        ContentEncoding = contentEncoding,
        JsonRequestBehavior = behavior,
        MaxJsonLength = Int32.MaxValue
    };
}

Дополнение:

Для тех, кто не совсем понимает, какие параметры нужно указывать, вызов метода может выглядеть так:

Json(
    new {
        field1 = true,
        field2 = "value"
    },
    "application/json",
    Encoding.UTF8,
    JsonRequestBehavior.AllowGet
);

Таким образом, вы можете создать JSON-ответ с указанными вами данными, типом контента и кодировкой. Не забудьте настроить MaxJsonLength, если ожидаете отправлять большие объёмы данных.

0

Если вы все еще получаете ошибку после настройки web.config, как показано ниже:

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

Я решил эту проблему следующим образом:

public ActionResult/JsonResult getData()
{
   var jsonResult = Json(superlargedata, JsonRequestBehavior.AllowGet);
   jsonResult.MaxJsonLength = int.MaxValue;
   return jsonResult;
}

Надеюсь, это поможет!

0

Вы можете настроить максимальную длину для JSON-запросов в вашем файле web.config следующим образом:

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

Значение по умолчанию для maxJsonLength составляет 102400. Для получения более подробной информации вы можете обратиться к этой странице на MSDN: http://msdn.microsoft.com/en-us/library/bb763183.aspx.

0

Я сталкивался с похожей проблемой в ASP.NET Web Forms, когда настройки из файла web.config полностью игнорировались. Я решил это, установив максимальную длину JSON вручную:

JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue; 
return serializer.Serialize(response);

Конечно, это далеко не лучшее решение. Если вы отправляете такое количество данных в вызове веб-сервиса, вам стоит рассмотреть другие подходы.

0

Я следовал ответу vestigal и пришёл к следующему решению:

Когда мне нужно было отправить большой JSON на действие в контроллере, я получал известную ошибку: "Ошибка при десериализации с использованием JSON JavaScriptSerializer. Длина строки превышает значение, установленное для свойства maxJsonLength.\r\nИмя параметра: input value provider".

Что я сделал — это создал новую фабрику ValueProvider, названную LargeJsonValueProviderFactory, и установил MaxJsonLength = Int32.MaxValue в методе GetDeserializedObject.

Вот код:

public sealed class LargeJsonValueProviderFactory : ValueProviderFactory
{
    private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value)
    {
        IDictionary<string, object> dictionary = value as IDictionary<string, object>;
        if (dictionary != null)
        {
            foreach (KeyValuePair<string, object> keyValuePair in dictionary)
                AddToBackingStore(backingStore, MakePropertyKey(prefix, keyValuePair.Key), keyValuePair.Value);
        }
        else
        {
            IList list = value as IList;
            if (list != null)
            {
                for (int index = 0; index < list.Count; ++index)
                    AddToBackingStore(backingStore, MakeArrayKey(prefix, index), list[index]);
            }
            else
                backingStore.Add(prefix, value);
        }
    }

    private static object GetDeserializedObject(ControllerContext controllerContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            return null;
        string end = new StreamReader(controllerContext.HttpContext.Request.InputStream).ReadToEnd();
        if (string.IsNullOrEmpty(end))
            return null;

        var serializer = new JavaScriptSerializer { MaxJsonLength = Int32.MaxValue };

        return serializer.DeserializeObject(end);
    }

    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        if (controllerContext == null)
            throw new ArgumentNullException(nameof(controllerContext));
        object deserializedObject = GetDeserializedObject(controllerContext);
        if (deserializedObject == null)
            return null;
        Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        AddToBackingStore(new EntryLimitedDictionary(dictionary), string.Empty, deserializedObject);
        return new DictionaryValueProvider<object>(dictionary, CultureInfo.CurrentCulture);
    }

    private static string MakeArrayKey(string prefix, int index)
    {
        return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
    }

    private static string MakePropertyKey(string prefix, string propertyName)
    {
        return string.IsNullOrEmpty(prefix) ? propertyName : prefix + "." + propertyName;
    }

    private class EntryLimitedDictionary
    {
        private static int _maximumDepth = GetMaximumDepth();
        private readonly IDictionary<string, object> _innerDictionary;
        private int _itemCount;

        public EntryLimitedDictionary(IDictionary<string, object> innerDictionary)
        {
            _innerDictionary = innerDictionary;
        }

        public void Add(string key, object value)
        {
            if (++_itemCount > _maximumDepth)
                throw new InvalidOperationException("JsonValueProviderFactory_RequestTooLarge");
            _innerDictionary.Add(key, value);
        }

        private static int GetMaximumDepth()
        {
            NameValueCollection appSettings = ConfigurationManager.AppSettings;
            if (appSettings != null)
            {
                string[] values = appSettings.GetValues("aspnet:MaxJsonDeserializerMembers");
                if (values != null && values.Length > 0 && int.TryParse(values[0], out int result))
                    return result;
            }
            return 1000;
        }
    }
}

Затем, в методе Application_Start из Global.asax.cs, я заменил ValueProviderFactory на новую:

protected void Application_Start()
{
    ...

    // Добавляем LargeJsonValueProviderFactory
    ValueProviderFactory jsonFactory = null;
    foreach (var factory in ValueProviderFactories.Factories)
    {
        if (factory.GetType().FullName == "System.Web.Mvc.JsonValueProviderFactory")
        {
            jsonFactory = factory;
            break;
        }
    }

    if (jsonFactory != null)
    {
        ValueProviderFactories.Factories.Remove(jsonFactory);
    }

    var largeJsonValueProviderFactory = new LargeJsonValueProviderFactory();
    ValueProviderFactories.Factories.Add(largeJsonValueProviderFactory);
}

Таким образом, я смог избежать ошибки и успешно обработать большой JSON.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь