Installing a standard JSON serializer in ASP.NET MVC

I am working on an existing application that has been partially converted to MVC. Whenever the controller responds with an ActionResult JSON, enumerations are sent as numbers opposite the string name. It looks like the default serial serializer should be JSON.Net, which should send enumerations as their names, opposite the integer representation, but that is not the case.

Am I missing the web.config setting, which sets this as the default serializer? Or is there another parameter that needs to be changed?

+55
c # asp.net-mvc asp.net-mvc-4
Jan 29 '13 at 20:35
source share
2 answers

In ASP.Net MVC4, the default JavaScript serializer, which is used in the JsonResult class, is still the JavaScriptSerializer (you can check this in code )

I think you confused it with ASP.Net Web.API, where JSON.Net is the standard JS serializer, but MVC4 does not use it.

So, you need to configure JSON.Net to work with MVC4 (basically you need to create your own JsonNetResult ), there are many articles about this:

If you also want to use JSON.Net for the parameters of the controller action, so during model binding you need to write your own implementation of ValueProviderFactory .

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 with Json.Net

+70
Jan 29 '13 at 20:47
source share

ASP.NET MVC 5 Fix:

I was not ready to switch to Json.NET yet, and in my case an error occurred during the request. The best approach in my scenario was to modify the actual JsonValueProviderFactory which applies the patch to the global project and can be done by editing the global.cs file as such.

 JsonValueProviderConfig.Config(ValueProviderFactories.Factories); 

add web.config entry:

 <add key="aspnet:MaxJsonLength" value="20971520" /> 

and then create the next two 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 custom aspnet:MaxJsonLength to configure web.config 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; } } 
0
Jun 03 '18 at 11:08
source share



All Articles