Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the default JSON serializer in ASP.NET MVC

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?

like image 705
John Avatar asked Jan 29 '13 20:01

John


People also ask

How to serialize to JSON?

NET objects as JSON (serialize) To write JSON to a string or to a file, call the JsonSerializer. Serialize method.

What is serialization in ASP NET MVC?

Serialization is the process of converting the state of an object into a form that can be persisted or transported.

What is JSON serialization and deserialization in C#?

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.


2 Answers

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:

  • ASP.NET MVC and Json.NET
  • Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?

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

like image 121
nemesv Avatar answered Sep 20 '22 08:09

nemesv


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;     } } 
like image 39
Maxim Gershkovich Avatar answered Sep 22 '22 08:09

Maxim Gershkovich