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