zoukankan      html  css  js  c++  java
  • 解决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即可,同时也兼顾了可配置的灵活性。

     

  • 相关阅读:
    分析java程序的命令总结jps,jstack
    Tomcat配置详解及tomcat的连接数与线程池
    Go入门练习题
    WebSocket的原理,及如何测试websocket是否连接成功
    day3-每天进步一点基础知识-正则练习题
    day2-每天进步一点基础知识
    day1-每天进步一点
    数组有没有length()这个方法? String有没有length()这个方法?
    List, Set, Map是否继承自Collection接口?
    启动一个线程是用run()还是start()?
  • 原文地址:https://www.cnblogs.com/shenba/p/2337050.html
Copyright © 2011-2022 走看看