Повертаємо багато тексту за допомогою JsonResult Avoid MaxJsonLength Exceeded Exception

6

Програмування 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.b__11() +20 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +251 System.Web.Mvc.c__DisplayClass16.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.b__4() +34 System.Web.Mvc.Async.c__DisplayClass1.b__0() +21 System.Web.Mvc.Async.c__DisplayClass8`1.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 Версія: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