2012-03-01 21 views
28

Recibo una excepción que indica que la solicitud JSON era demasiado grande para deserializarla.JsonValueProviderFactory arroja "solicitud demasiado grande"

Viene de la JsonValueProviderFactory ....

La aplicación MVC cuenta actualmente con un aglomerante modelo personalizado utilizando Json.Net que no tiene ningún problema deserializar los datos JSON. Sin embargo, supongo que el proveedor de valores JSON predeterminado se está tropezando. o tiene algún límite raro incorporado?

Puede ser que tenga que ver con la última versión de MVC4 ya que al usar la versión anterior de MVC4 no hubo problemas con grandes cantidades de JSON.

Entonces, ¿hay alguna manera de cambiar la configuración del encuadernador de valores json real?

pasando por http://haacked.com/archive/2011/06/30/whatrsquos-the-difference-between-a-value-provider-and-model-binder.aspx

Me da la impresión de que es algo personalizado que lo convierte en un diccionario .... No puedo encontrar ningún código fuente relacionado con él o si hay alguna configuración que puedo cambiar?

¿O existe una ValueBinder alternativa que podría usar?

o alguna otra opción?

Server Error in '/' Application. 
The JSON request was too large to be deserialized. 
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: The JSON request was too large to be deserialized. 

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: The JSON request was too large to be deserialized.] 
    System.Web.Mvc.EntryLimitedDictionary.Add(String key, Object value) +464621 
    System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) +413 
    System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) +164 
    System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) +164 
    System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) +373 
    System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) +164 
    System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) +116 
    System.Web.Mvc.<>c__DisplayClassc.<GetValueProvider>b__7(ValueProviderFactory factory) +34 

     System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +151 
    System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +177 

Respuesta

64

Si utiliza JSON.NET para la serialización/deserialización, se puede sustituir el valor por defecto JsonValueProviderFactory con uno personalizado como se muestra en this blog post:

public sealed class JsonDotNetValueProviderFactory : ValueProviderFactory 
{ 
    public override IValueProvider GetValueProvider(ControllerContext controllerContext) 
    { 
     if (controllerContext == null) 
      throw new ArgumentNullException("controllerContext"); 

     if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) 
      return null; 

     var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream); 
     var bodyText = reader.ReadToEnd(); 

     return String.IsNullOrEmpty(bodyText) ? null : new DictionaryValueProvider<object>(JsonConvert.DeserializeObject<ExpandoObject>(bodyText, new ExpandoObjectConverter()) , CultureInfo.CurrentCulture); 
    } 
} 

y en su Application_Start:

ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault()); 
ValueProviderFactories.Factories.Add(new JsonDotNetValueProviderFactory()); 

y si desea seguir con la fábrica predeterminada que utiliza la clase JavaScriptSerializer, puede ajustar el maxJsonLength propiedad en su web.config:

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

y tristemente que sólo reciben una pequeña cantidad de reputación de esto, en la que alguien que responde a la manera de dividir un stirng en C# recibirá cargas de cubo :) ¡Gracias! fue realmente útil ... curiosamente, hacer que maxJsonLength sea más grande no funcionó. Tengo la sensación de que puede haber un error en el archivador predeterminado de Json Value –

+0

Como mi carpeta de modelo personalizada maneja todo, solo llamé al remove. ¡No quiero deserializar doblemente todo! –

+0

¿Qué sucede si envío una 'cadena' y la deserializo con JSON.NET? ¿Alguna vez recibiré un error si la cadena es demasiado grande? –

61

Para mí, no se excedió maxJsonLength. Tuve que agregar lo siguiente:

<appSettings> 
    <add key="aspnet:MaxJsonDeserializerMembers" value="150000" /> 
</appSettings> 

Funcionó una delicia después de eso.

+3

héroe ... He estado gastando años obteniendo en ninguna parte escribiendo nuevos controladores para la serialización, cuando fue esto todo el tiempo ... gracias ... –

+2

Yo también, este era el problema. –

+1

¡¡¡Gran respuesta !!! ¡Me ayudó!¡Muchas gracias! – Bronek

3

Las sugerencias anteriores no funcionaron para mí hasta que probé esto:

// Global.asax.cs  
protected void Application_Start() { 
    MiniProfiler.Settings.MaxJsonResponseSize = int.MaxValue; 
} 
Cuestiones relacionadas