.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 的问题终于解决了!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值