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