zoukankan      html  css  js  c++  java
  • .NET MVC JSON JavaScriptSerializer 字符串的长度超过 maxJsonLength 值问题的解决

    1 [ArgumentException: 使用 JSON JavaScriptSerializer 序列化或还原序列化期间发生错误。字符串的长度超过在 maxJsonLength 属性上设定的值。
    2 参数名称: input]
    3    System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit) +168
    4    System.Web.Mvc.JsonValueProviderFactory.GetDeserializedObject(ControllerContext controllerContext) +213
    5    System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) +16
    6    System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) +69
    7    System.Web.Mvc.ControllerBase.get_ValueProvider() +30  

    于前端 Post 到 Action 的参数太大,超过了2M,还没进入后台的 Action 方法就报错了。这个问题困扰了很久,一直未解决。网上找了几个方法都无效。

    在 web.config 中加入这些,没有作用:

     
    1
    2
    3
    4
    <appSettings>
      <add key="aspnet:MaxJsonDeserializerMembers" value="2147483647" />
      <add key="aspnet:UpdatePanelMaxScriptLength" value="2147483647" />
    </appSettings>

    在 web.config 中加入这些,也没有作用:

     
    1
    2
    3
    4
    5
    6
    7
    8
    <system.web.extensions>
      <scripting>
        <webServices>
          <jsonSerialization maxJsonLength="2147483647">
          </jsonSerialization>
        </webServices>
      </scripting>
    </system.web.extensions>

    仔细看了一下异常信息,发现,是在System.Web.Mvc.JsonValueProviderFactory 里调用的 JavaScriptSerializer:

    于是查了一下 ,发现 JsonValueProviderFactory 在 System.Web.Mvc.dll 程序集里的:

    反编译 System.Web.Mvc.dll 找到 JsonValueProviderFactory 类:

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Globalization;
    using System.IO;
    using System.Web.Mvc.Properties;
    using System.Web.Script.Serialization;
    namespace System.Web.Mvc
    {
        public sealed class JsonValueProviderFactory : ValueProviderFactory
        {
            private class EntryLimitedDictionary
            {
                private static int _maximumDepth = JsonValueProviderFactory.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 > JsonValueProviderFactory.EntryLimitedDictionary._maximumDepth)
                    {
                        throw new InvalidOperationException(MvcResources.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;
                }
            }
            private static void AddToBackingStore(JsonValueProviderFactory.EntryLimitedDictionary backingStore, string prefix, object value)
            {
                IDictionary<string, object> dictionary = value as IDictionary<string, object>;
                if (dictionary != null)
                {
                    foreach (KeyValuePair<string, object> current in dictionary)
                    {
                        JsonValueProviderFactory.AddToBackingStore(backingStore, JsonValueProviderFactory.MakePropertyKey(prefix, current.Key), current.Value);
                    }
                    return;
                }
                IList list = value as IList;
                if (list != null)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        JsonValueProviderFactory.AddToBackingStore(backingStore, JsonValueProviderFactory.MakeArrayKey(prefix, i), list[i]);
                    }
                    return;
                }
                backingStore.Add(prefix, value);
            }
            private static object GetDeserializedObject(ControllerContext controllerContext)
            {
                if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
                {
                    return null;
                }
                StreamReader streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
                string text = streamReader.ReadToEnd();
                if (string.IsNullOrEmpty(text))
                {
                    return null;
                }
                // 问题就出在这里,没有给 javaScriptSerializer.MaxJsonLength 赋值,其默认值是 2097152 字节,即2M
                JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
                return javaScriptSerializer.DeserializeObject(text);
            }
            public override IValueProvider GetValueProvider(ControllerContext controllerContext)
            {
                if (controllerContext == null)
                {
                    throw new ArgumentNullException("controllerContext");
                }
                object deserializedObject = JsonValueProviderFactory.GetDeserializedObject(controllerContext);
                if (deserializedObject == null)
                {
                    return null;
                }
                Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
                JsonValueProviderFactory.EntryLimitedDictionary backingStore = new JsonValueProviderFactory.EntryLimitedDictionary(dictionary);
                JsonValueProviderFactory.AddToBackingStore(backingStore, 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)
            {
                if (!string.IsNullOrEmpty(prefix))
                {
                    return prefix + "." + propertyName;
                }
                return propertyName;
            }
        }
    }

    在 JavaScriptSerializer 没有设置 MaxJsonLength,默认值是 2097152 字节,即2M。 

    解决此问题的方法就是 把 javaScriptSerializer.MaxJsonLength = int.MaxValue; (int.MaxValue 值是 2147483647 字节,即2048M)

    自己重写类 JsonValueProviderFactory 命名为 MyJsonValueProviderFactory:

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Globalization;
    using System.IO;
    using System.Web.Mvc;
    using System.Web.Mvc.Properties;
    using System.Web.Script.Serialization;
    namespace XXX
    {
        public sealed class MyJsonValueProviderFactory : ValueProviderFactory
        {
            private class EntryLimitedDictionary
            {
                private static int _maximumDepth = 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 > _maximumDepth)
                    {
                        //throw new InvalidOperationException(MvcResources.JsonValueProviderFactory_RequestTooLarge);
                        throw new InvalidOperationException("itemCount is over maximumDepth");
                    }
                    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;
                }
            }
     
            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> current in dictionary)
                    {
                        AddToBackingStore(backingStore, MakePropertyKey(prefix, current.Key), current.Value);
                    }
                    return;
                }
                IList list = value as IList;
                if (list != null)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        AddToBackingStore(backingStore, MakeArrayKey(prefix, i), list[i]);
                    }
                    return;
                }
                backingStore.Add(prefix, value);
            }
     
            private static object GetDeserializedObject(ControllerContext controllerContext)
            {
                if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
                {
                    return null;
                }
                StreamReader streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
                string text = streamReader.ReadToEnd();
                if (string.IsNullOrEmpty(text))
                {
                    return null;
                }
                JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
                // 解决这个问题:
                // 使用 JSON JavaScriptSerializer 序列化或还原序列化期间发生错误。字符串的长度超过在 maxJsonLength 属性上设定的值。
                javaScriptSerializer.MaxJsonLength = int.MaxValue;
                // ----------------------------------------
                return javaScriptSerializer.DeserializeObject(text);
            }
     
            public override IValueProvider GetValueProvider(ControllerContext controllerContext)
            {
                if (controllerContext == null)
                {
                    throw new ArgumentNullException("controllerContext");
                }
                object deserializedObject = GetDeserializedObject(controllerContext);
                if (deserializedObject == null)
                {
                    return null;
                }
                Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
                EntryLimitedDictionary backingStore = new EntryLimitedDictionary(dictionary);
                AddToBackingStore(backingStore, 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)
            {
                if (!string.IsNullOrEmpty(prefix))
                {
                    return prefix + "." + propertyName;
                }
                return propertyName;
            }
        }
    }

    然后在 Global.asax 中的 Application_Start() 方法里,加入如下代码,用 MyJsonValueProviderFactory 类代替 System.Web.Mvc.dll 程序集中的 JsonValueProviderFactory 类。

     
    1
    2
    ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
    ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());

     至此,.NET MVC 超出 maxJsonLength 的问题终于解决了!

  • 相关阅读:
    Something I know about WebDynpro
    Details about support package implementation
    CRM Middleware Performance Topics
    Way to configure the logon navigaion layouts via Business Roles in CRM
    DOM 常用节点类型和方法
    第一届 xdef 会议日程
    去除百度音乐盒广告的chrome插件 持续更新
    从人人网抓取高校数据信息,包括,省份 高校 院系 (提供最终SQL文件下载)
    PHP 与 JSON
    解决HTTPS 发送请求走socket问题
  • 原文地址:https://www.cnblogs.com/yanglang/p/8830837.html
Copyright © 2011-2022 走看看