解決MVC中JSON字符長度超出限制的異常


今日碰到了這么一個異常,異常信息如下:

Type : System.InvalidOperationException, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : 使用 JSON JavaScriptSerializer 進行序列化或反序列化時出錯。字符串
的長度超過了為 maxJsonLength 屬性設置的值。
Source : System.Web.Extensions
Help link : 
Data : System.Collections.ListDictionaryInternal
TargetSite : Void Serialize(System.Object, System.Text.StringBuilder,
SerializationFormat)
Stack Trace :    在
System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj,
StringBuilder output, SerializationFormat serializationFormat)
   在 System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object
obj, SerializationFormat serializationFormat)
   在 System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object
 

這個異常是在執行MVC中的JsonResult的時拋出的,根據異常的Message得知是序列化的字符串超出了maxJsonLength的限制。並得知這個屬性是由JavaScriptSerializer提供的,因為MVC內置的JsonResult是用JavaScriptSerializer進行序列化的。在網上快速搜索了一下,碰到這個問題的童鞋不少,大部分推薦的解決的方法都是在web.config中加入以下配置,設置maxJsonLength的長度即可。

View Code
< system.web.extensions >
        < scripting >
            < webServices >
                < jsonSerialization  maxJsonLength ="20971520" />
            </ webServices >
        </ scripting >
    </ system.web.extensions >

在自動提示下,很順暢的加上了幾行代碼,以為這是個簡潔的解決方案,但是運行網站之后報以下錯誤:

分析器錯誤消息: 無法識別的配置節 system.web.extensions。
這似乎又是碰到了一家人不認識的情況,既然無法識別為什么能帶智能感知的方式輸出,而且是已system.web開頭的,按道理不會識別不出的。以為是拼寫錯誤,經過進一步搜索之后,原來是缺乏了聲明,加上對節點的聲明即可(很大一串的內容)。

 

View Code
< sectionGroup  name ="system.web.extensions"  type ="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
           < sectionGroup  name ="scripting"  type ="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
               < section  name ="scriptResourceHandler"  type ="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
               < sectionGroup  name ="webServices"  type ="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" >
                   < section  name ="jsonSerialization"  type ="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="Everywhere" />
                   < section  name ="profileService"  type ="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
                   < section  name ="authenticationService"  type ="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
                   < section  name ="roleService"  type ="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"  requirePermission ="false"  allowDefinition ="MachineToApplication" />
               </ sectionGroup >
           </ sectionGroup >
       </ sectionGroup >

 加入了聲明之后,運行正常,但是問題依舊還在,而且不管maxJsonLength設置成多大都無效,就算改成1個字符,居然還能跑起來。碰到這個問題只能進一步的搜索。在這篇文章中找到了原委http://weblogs.asp.net/rashid/archive/2009/03/23/submitting-my-first-bug-after-asp-net-mvc-1-0-rtm-release.aspx

原來MVC框架內置的JsonResult代碼中,在使用JavaScriptSerializer時,都是采用的默認值,沒有從maxJsonLength讀取值,即忽略了這個配置。要想使用配置中的值,只能自定義一個JsonResult,重寫原JsonResult的ExecuteResult方法,於是定義一個ConfigurableJsonResult,代碼如下:

ConfigurableJsonResult
 1  public class ConfigurableJsonResult : JsonResult
 2     {
 3         public override void ExecuteResult(ControllerContext context)
 4         {
 5             if (context == null)
 6             {
 7                 throw new ArgumentNullException("context");
 8             }
 9             if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
10                 String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
11             {
12                 throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
13             }
14 
15             HttpResponseBase response = context.HttpContext.Response;
16 
17             if (!String.IsNullOrEmpty(ContentType))
18             {
19                 response.ContentType = ContentType;
20             }
21             else
22             {
23                 response.ContentType = "application/json";
24             }
25             if (ContentEncoding != null)
26             {
27                 response.ContentEncoding = ContentEncoding;
28             }
29             if (Data != null)
30             {
31                 JavaScriptSerializer serializer = new JavaScriptSerializer();
32 
33                  ScriptingJsonSerializationSection section = ConfigurationManager.GetSection("system.web.extensions/scripting/webServices/jsonSerialization") as ScriptingJsonSerializationSection;
34            
35                  if (section != null)
36                  {
37                      serializer.MaxJsonLength = section.MaxJsonLength;
38                      serializer.RecursionLimit = section.RecursionLimit;
39                  }
40 
41                 response.Write(serializer.Serialize(Data));
42             }
43         }
44     }

關鍵在紅色標記的代碼,讀取配置的值。JavaScriptSerializer還有其他屬性可配置,沒有列出與實現,暫時夠用。

這樣在返回長字符內容的json結果時,直接替換原JsonResult即可,同時也兼顧了可配置的靈活性。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM