G+

Возвращаем много текста с помощью JsonResult Avoid MaxJsonLength Exceeded Exception

Программирование Asp.net
Предыдущий Следующий

  С появлением jquery стало очень удобно с  работать Ajax. И теперь при работе с Grid я обращаюсь к методам контролера, которые возвращает информацию в Json формате. Не знаю правильно ли это, но очень удобно. Но в таком подходе есть свои проблемы. По умолчанию количество символов передаваемых таким методом ограничено. И сервер выдает ошибку:


Server Error in ‘/’ Application.

Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.

Source Error: 

 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 

 

[InvalidOperationException: Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.]    System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat) +551497    System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, SerializationFormat serializationFormat) +74    System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj) +6    System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext context) +341    System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +10    System.Web.Mvc.<>c__DisplayClass14.<InvokeActionResultWithFilters>b__11() +20    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +251    System.Web.Mvc.<>c__DisplayClass16.<InvokeActionResultWithFilters>b__13() +19    System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +178    System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +314    System.Web.Mvc.Controller.ExecuteCore() +105    System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +39    System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7    System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +34    System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21    System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12    System.Web.Mvc.Async.WrappedAsyncResult`1.End() +59    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +44    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +7    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8682542    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155 

 


Version Information: Microsoft .NET Framework Version:2.0.50727.4952; ASP.NET Version:2.0.50727.4955

Поискал в интернете, и нашел решение проблемы.

Ошибка находится внутри обращения MVC к BCL.

if (Data != null) {
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    response.Write(serializer.Serialize(Data));
}
Во время сериализации сервер падает.

public string Serialize(object obj) {
    return Serialize(obj, SerializationFormat.JSON);
}

private string Serialize(object obj, SerializationFormat serializationFormat) {
    StringBuilder sb = new StringBuilder();
    Serialize(obj, sb, serializationFormat);
    return sb.ToString();
}

internal void Serialize(object obj, StringBuilder output, SerializationFormat serializationFormat) {
    SerializeValue(obj, output, 0, null, serializationFormat);
    // DevDiv Bugs 96574: Max JSON length does not apply when serializing to Javascript for ScriptDescriptors
    if (serializationFormat == SerializationFormat.JSON && output.Length > MaxJsonLength) {
        throw new InvalidOperationException(AtlasWeb.JSON_MaxJsonLengthExceeded);
    }
}
 

Т.е. стоит ограничение в 96574 символов. Мы должны реализовать наш собственный ActionResult, который будет генерировать JSON любого размера. Код:

using System;
using System.Web.Script.Serialization;

namespace System.Web.Mvc
{
    public class LargeJsonResult : JsonResult
    {
        const string JsonRequest_GetNotAllowed = "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.";
        public LargeJsonResult()
        {
            MaxJsonLength = 1024000;
            RecursionLimit = 100;
        }

        public int MaxJsonLength { get; set; }
        public int RecursionLimit { get; set; }

        public override void ExecuteResult( ControllerContext context )
        {
            if( context == null )
            {
                throw new ArgumentNullException( "context" );
            }
            if( JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
                String.Equals( context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase ) )
            {
                throw new InvalidOperationException( JsonRequest_GetNotAllowed );
            }

            HttpResponseBase response = context.HttpContext.Response;

            if( !String.IsNullOrEmpty( ContentType ) )
            {
                response.ContentType = ContentType;
            }
            else
            {
                response.ContentType = "application/json";
            }
            if( ContentEncoding != null )
            {
                response.ContentEncoding = ContentEncoding;
            }
            if( Data != null )
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer() { MaxJsonLength = MaxJsonLength, RecursionLimit = RecursionLimit };
                response.Write( serializer.Serialize( Data ) );
            }
        }
    }
}

Теперь мы можем использовать этот класс:

return new LargeJsonResult() { Data = output, MaxJsonLength = int.MaxValue };

Так же нужно подправить web.config

<system.web.extensions>
    <scripting>
      <webServices>
        <jsonSerialization maxJsonLength="2147483644"  />
      </webServices>
    </scripting>
  </system.web.extensions>

 

Комментарий:
Самостоятельный отпуск Опыт заказа вывоза мусора в Киеве