Can I set an unlimited length for maxJsonLength in

2018-12-31 01:20发布

I am using the autocomplete feature of jQuery. When I try to retrieve the list of more then 17000 records (each won't have more than 10 char length), it's exceeding the length and throws the error:

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.

Can I set an unlimited length for maxJsonLength in web.config? If not, what is the maximum length I can set?

27条回答
浮光初槿花落
2楼-- · 2018-12-31 01:56

Alternative ASP.NET MVC 5 Fix:

(Mine is similar to MFCs answer above with a few small changes)

I wasn't ready to change to Json.NET just yet and in my case the error was occurring during the request. Best approach in my scenario was modifying the actual JsonValueProviderFactory which applies the fix to the global project and can be done by editing the global.cs file as such.

JsonValueProviderConfig.Config(ValueProviderFactories.Factories);

add a web.config entry:

<add key="aspnet:MaxJsonLength" value="20971520" />

and then create the two following classes

public class JsonValueProviderConfig
{
    public static void Config(ValueProviderFactoryCollection factories)
    {
        var jsonProviderFactory = factories.OfType<JsonValueProviderFactory>().Single();
        factories.Remove(jsonProviderFactory);
        factories.Add(new CustomJsonValueProviderFactory());
    }
}

This is basically an exact copy of the default implementation found in System.Web.Mvc but with the addition of a configurable web.config appsetting value aspnet:MaxJsonLength.

public class CustomJsonValueProviderFactory : ValueProviderFactory
{

    /// <summary>Returns a JSON value-provider object for the specified controller context.</summary>
    /// <returns>A JSON value-provider object for the specified controller context.</returns>
    /// <param name="controllerContext">The controller context.</param>
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        if (controllerContext == null)
            throw new ArgumentNullException("controllerContext");

        object deserializedObject = CustomJsonValueProviderFactory.GetDeserializedObject(controllerContext);
        if (deserializedObject == null)
            return null;

        Dictionary<string, object> strs = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        CustomJsonValueProviderFactory.AddToBackingStore(new CustomJsonValueProviderFactory.EntryLimitedDictionary(strs), string.Empty, deserializedObject);

        return new DictionaryValueProvider<object>(strs, CultureInfo.CurrentCulture);
    }

    private static object GetDeserializedObject(ControllerContext controllerContext)
    {
        if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
            return null;

        string fullStreamString = (new StreamReader(controllerContext.HttpContext.Request.InputStream)).ReadToEnd();
        if (string.IsNullOrEmpty(fullStreamString))
            return null;

        var serializer = new JavaScriptSerializer()
        {
            MaxJsonLength = CustomJsonValueProviderFactory.GetMaxJsonLength()
        };
        return serializer.DeserializeObject(fullStreamString);
    }

    private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value)
    {
        IDictionary<string, object> strs = value as IDictionary<string, object>;
        if (strs != null)
        {
            foreach (KeyValuePair<string, object> keyValuePair in strs)
                CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakePropertyKey(prefix, keyValuePair.Key), keyValuePair.Value);

            return;
        }

        IList lists = value as IList;
        if (lists == null)
        {
            backingStore.Add(prefix, value);
            return;
        }

        for (int i = 0; i < lists.Count; i++)
        {
            CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakeArrayKey(prefix, i), lists[i]);
        }
    }

    private class EntryLimitedDictionary
    {
        private static int _maximumDepth;

        private readonly IDictionary<string, object> _innerDictionary;

        private int _itemCount;

        static EntryLimitedDictionary()
        {
            _maximumDepth = CustomJsonValueProviderFactory.GetMaximumDepth();
        }

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

        public void Add(string key, object value)
        {
            int num = this._itemCount + 1;
            this._itemCount = num;
            if (num > _maximumDepth)
            {
                throw new InvalidOperationException("The length of the string exceeds the value set on the maxJsonLength property.");
            }
            this._innerDictionary.Add(key, value);
        }
    }

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

    private static string MakePropertyKey(string prefix, string propertyName)
    {
        if (string.IsNullOrEmpty(prefix))
        {
            return propertyName;
        }
        return string.Concat(prefix, ".", propertyName);
    }

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

    private static int GetMaxJsonLength()
    {
        int num;
        NameValueCollection appSettings = ConfigurationManager.AppSettings;
        if (appSettings != null)
        {
            string[] values = appSettings.GetValues("aspnet:MaxJsonLength");
            if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
            {
                return num;
            }
        }
        return 1000;
    }
}
查看更多
柔情千种
3楼-- · 2018-12-31 01:59

you can write this line into Controller

json.MaxJsonLength = 2147483644;

you can also write this line into web.config

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

`

To be on the safe side, use both.

查看更多
永恒的永恒
4楼-- · 2018-12-31 02:01

Simply set MaxJsonLength proprty in MVC's Action method

JsonResult json= Json(classObject, JsonRequestBehavior.AllowGet);
json.MaxJsonLength = int.MaxValue;
return json;
查看更多
忆尘夕之涩
5楼-- · 2018-12-31 02:04

if you are still getting error after web.config setting like following:

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

I solved it by following:

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

I hope this should help.

查看更多
墨雨无痕
6楼-- · 2018-12-31 02:06

In MVC 4 you can do:

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

in your controller.

Addition:

For anyone puzzled by the parameters you need to specify, a call could look like this:

Json(
    new {
        field1 = true,
        field2 = "value"
        },
    "application/json",
    Encoding.UTF8,
    JsonRequestBehavior.AllowGet
);
查看更多
泪湿衣
7楼-- · 2018-12-31 02:06

I followed vestigal's answer and got to this solution:

When I needed to post a large json to an action in a controller, I would get the famous "Error during deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.\r\nParameter name: input value provider".

What I did is create a new ValueProviderFactory, LargeJsonValueProviderFactory, and set the MaxJsonLength = Int32.MaxValue in the GetDeserializedObject method

public sealed class LargeJsonValueProviderFactory : ValueProviderFactory
{
private static void AddToBackingStore(LargeJsonValueProviderFactory.EntryLimitedDictionary backingStore, string prefix, object value)
{
    IDictionary<string, object> dictionary = value as IDictionary<string, object>;
    if (dictionary != null)
    {
        foreach (KeyValuePair<string, object> keyValuePair in (IEnumerable<KeyValuePair<string, object>>) dictionary)
            LargeJsonValueProviderFactory.AddToBackingStore(backingStore, LargeJsonValueProviderFactory.MakePropertyKey(prefix, keyValuePair.Key), keyValuePair.Value);
    }
    else
    {
        IList list = value as IList;
        if (list != null)
        {
            for (int index = 0; index < list.Count; ++index)
                LargeJsonValueProviderFactory.AddToBackingStore(backingStore, LargeJsonValueProviderFactory.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 (object) null;
    string end = new StreamReader(controllerContext.HttpContext.Request.InputStream).ReadToEnd();
    if (string.IsNullOrEmpty(end))
        return (object) null;

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

    return serializer.DeserializeObject(end);
}

/// <summary>Returns a JSON value-provider object for the specified controller context.</summary>
/// <returns>A JSON value-provider object for the specified controller context.</returns>
/// <param name="controllerContext">The controller context.</param>
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
    if (controllerContext == null)
        throw new ArgumentNullException("controllerContext");
    object deserializedObject = LargeJsonValueProviderFactory.GetDeserializedObject(controllerContext);
    if (deserializedObject == null)
        return (IValueProvider) null;
    Dictionary<string, object> dictionary = new Dictionary<string, object>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
    LargeJsonValueProviderFactory.AddToBackingStore(new LargeJsonValueProviderFactory.EntryLimitedDictionary((IDictionary<string, object>) dictionary), string.Empty, deserializedObject);
    return (IValueProvider) new DictionaryValueProvider<object>((IDictionary<string, object>) dictionary, CultureInfo.CurrentCulture);
}

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

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

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

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

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

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

}

Then, in the Application_Start method from Global.asax.cs, replace the ValueProviderFactory with the new one:

protected void Application_Start()
{
    ...

    //Add 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);
}
查看更多
登录 后发表回答