net - web api json c#
ConfiguraciĆ³n del serializador JSON predeterminado en ASP.NET MVC (2)
Corrección de ASP.NET MVC 5:
Todavía no estaba listo para cambiar a Json.NET y en mi caso el error se produjo durante la solicitud. El mejor enfoque en mi escenario fue modificar el JsonValueProviderFactory
real que aplica el arreglo al proyecto global y se puede hacer editando el archivo global.cs
como tal.
JsonValueProviderConfig.Config(ValueProviderFactories.Factories);
agregue una entrada web.config:
<add key="aspnet:MaxJsonLength" value="20971520" />
y luego crea las dos clases siguientes
public class JsonValueProviderConfig
{
public static void Config(ValueProviderFactoryCollection factories)
{
var jsonProviderFactory = factories.OfType<JsonValueProviderFactory>().Single();
factories.Remove(jsonProviderFactory);
factories.Add(new CustomJsonValueProviderFactory());
}
}
Esta es básicamente una copia exacta de la implementación predeterminada que se encuentra en System.Web.Mvc
pero con la adición de un valor de aspnet:MaxJsonLength
web.config configurable aspnet:MaxJsonLength
.
public class CustomJsonValueProviderFactory : ValueProviderFactory
{
/// <summary>Returns a JSON value-provider object for the specified controller context.</summary>
/// <returns>A JSON value-provider object for the specified controller context.</returns>
/// <param name="controllerContext">The controller context.</param>
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
object deserializedObject = CustomJsonValueProviderFactory.GetDeserializedObject(controllerContext);
if (deserializedObject == null)
return null;
Dictionary<string, object> strs = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
CustomJsonValueProviderFactory.AddToBackingStore(new CustomJsonValueProviderFactory.EntryLimitedDictionary(strs), string.Empty, deserializedObject);
return new DictionaryValueProvider<object>(strs, CultureInfo.CurrentCulture);
}
private static object GetDeserializedObject(ControllerContext controllerContext)
{
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
return null;
string fullStreamString = (new StreamReader(controllerContext.HttpContext.Request.InputStream)).ReadToEnd();
if (string.IsNullOrEmpty(fullStreamString))
return null;
var serializer = new JavaScriptSerializer()
{
MaxJsonLength = CustomJsonValueProviderFactory.GetMaxJsonLength()
};
return serializer.DeserializeObject(fullStreamString);
}
private static void AddToBackingStore(EntryLimitedDictionary backingStore, string prefix, object value)
{
IDictionary<string, object> strs = value as IDictionary<string, object>;
if (strs != null)
{
foreach (KeyValuePair<string, object> keyValuePair in strs)
CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakePropertyKey(prefix, keyValuePair.Key), keyValuePair.Value);
return;
}
IList lists = value as IList;
if (lists == null)
{
backingStore.Add(prefix, value);
return;
}
for (int i = 0; i < lists.Count; i++)
{
CustomJsonValueProviderFactory.AddToBackingStore(backingStore, CustomJsonValueProviderFactory.MakeArrayKey(prefix, i), lists[i]);
}
}
private class EntryLimitedDictionary
{
private static int _maximumDepth;
private readonly IDictionary<string, object> _innerDictionary;
private int _itemCount;
static EntryLimitedDictionary()
{
_maximumDepth = CustomJsonValueProviderFactory.GetMaximumDepth();
}
public EntryLimitedDictionary(IDictionary<string, object> innerDictionary)
{
this._innerDictionary = innerDictionary;
}
public void Add(string key, object value)
{
int num = this._itemCount + 1;
this._itemCount = num;
if (num > _maximumDepth)
{
throw new InvalidOperationException("The length of the string exceeds the value set on the maxJsonLength property.");
}
this._innerDictionary.Add(key, value);
}
}
private static string MakeArrayKey(string prefix, int index)
{
return string.Concat(prefix, "[", index.ToString(CultureInfo.InvariantCulture), "]");
}
private static string MakePropertyKey(string prefix, string propertyName)
{
if (string.IsNullOrEmpty(prefix))
{
return propertyName;
}
return string.Concat(prefix, ".", propertyName);
}
private static int GetMaximumDepth()
{
int num;
NameValueCollection appSettings = ConfigurationManager.AppSettings;
if (appSettings != null)
{
string[] values = appSettings.GetValues("aspnet:MaxJsonDeserializerMembers");
if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
{
return num;
}
}
return 1000;
}
private static int GetMaxJsonLength()
{
int num;
NameValueCollection appSettings = ConfigurationManager.AppSettings;
if (appSettings != null)
{
string[] values = appSettings.GetValues("aspnet:MaxJsonLength");
if (values != null && values.Length != 0 && int.TryParse(values[0], out num))
{
return num;
}
}
return 1000;
}
}
Estoy trabajando en una aplicación existente que se ha convertido parcialmente a MVC. Cada vez que un controlador responde con un JSON ActionResult, las enumeraciones se envían como números opuestos al nombre de la cadena. Parece que el serializador predeterminado debe ser JSON.Net, que debería estar enviando las enumeraciones como sus nombres opuestos a la representación entera, pero ese no es el caso aquí.
¿Me falta una configuración web.config que establezca esto como el serializador predeterminado? ¿O hay otra configuración que debe cambiarse?
En ASP.Net MVC4, el serializador de JavaScript predeterminado que se utiliza en la clase JsonResult
sigue siendo el JavaScriptSerializer (puede verificarlo en el code )
Creo que lo ha confundido con ASP.Net Web.API, donde JSON.Net es el serializador JS predeterminado pero MVC4 no lo usa.
Entonces, necesita configurar JSON.Net para que funcione con MVC4 (básicamente, necesita crear su propio JsonNetResult
), hay muchos artículos al respecto:
- ASP.NET MVC y Json.NET
- Usando JSON.NET como el serializador JSON predeterminado en ASP.NET MVC 3, ¿es posible?
Si también desea usar JSON.Net para los parámetros de acción del controlador, entonces durante el enlace del modelo, necesita escribir su propia implementación de ValueProviderFactory
.
Y necesita registrar su implementación con:
ValueProviderFactories.Factories
.Remove(ValueProviderFactories.Factories
.OfType<JsonValueProviderFactory>().Single());
ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());
Puede usar el JsonValueProviderFactory
como un ejemplo o este artículo: ASP.NET MVC 3 - JsonValueProviderFactory mejorado utilizando Json.Net