I'm working on an existing application that has been partially converted over to MVC. Whenever a controller responds with a JSON ActionResult, the enums are sent as numbers opposed to the string name. It sounds like the default serializer should be JSON.Net, which should be sending the enums over as their names opposed to the integer representation, but that's not the case here.
Am I missing a web.config setting that sets this as the default serializer? Or is there another setting that needs to be changed?
NET objects as JSON (serialize) To write JSON to a string or to a file, call the JsonSerializer. Serialize method.
Serialization is the process of converting the state of an object into a form that can be persisted or transported.
Serialization is the process of converting . NET objects such as strings into a JSON format and deserialization is the process of converting JSON data into . NET objects.
In ASP.Net MVC4 the default JavaScript serializer which is used in the JsonResult
class is still the JavaScriptSerializer (you can check it in the code)
I think you have confused it with the ASP.Net Web.API where JSON.Net is the default JS serializer but MVC4 doesn't use it.
So you need to configure JSON.Net to work with MVC4 (basically you need to create your own JsonNetResult
), there are plenty of articles about it:
If you also want to use JSON.Net for controller action parameters so during the model binding then you need write your own ValueProviderFactory
implementation.
And you need to register your implementation with:
ValueProviderFactories.Factories .Remove(ValueProviderFactories.Factories .OfType<JsonValueProviderFactory>().Single()); ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());
You can use the built in JsonValueProviderFactory
as an example or this article: ASP.NET MVC 3 – Improved JsonValueProviderFactory using Json.Net
ASP.NET MVC 5 Fix:
I wasn't ready to change to Json.NET just yet and in my case the error was occurring during the request. Best approach in my scenario was modifying the actual JsonValueProviderFactory
which applies the fix to the global project and can be done by editing the global.cs
file as such.
JsonValueProviderConfig.Config(ValueProviderFactories.Factories);
add a web.config entry:
<add key="aspnet:MaxJsonLength" value="20971520" />
and then create the two following classes
public class JsonValueProviderConfig { public static void Config(ValueProviderFactoryCollection factories) { var jsonProviderFactory = factories.OfType<JsonValueProviderFactory>().Single(); factories.Remove(jsonProviderFactory); factories.Add(new CustomJsonValueProviderFactory()); } }
This is basically an exact copy of the default implementation found in System.Web.Mvc
but with the addition of a configurable web.config appsetting value 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; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With