Instellen van de standaard JSON-serializer in ASP.NET MVC

Ik werk aan een bestaande applicatie die gedeeltelijk naar MVC is geconverteerd. Telkens wanneer een controller reageert met een JSON-actieResult, worden de ENUM’s verzonden als cijfers in tegenstelling tot de tekenreeksnaam. Het klinkt alsof de standaardserializer JSON.net moet zijn, wat de ENUM’s moet sturen als hun namen die zich tegen de getal-weergave in tegenstelling hebben, maar dat is hier niet het geval.

Ik mis ik een web.config-instelling die dit instelt als de standaardserializer? Of is er een andere instelling die moet worden gewijzigd?


Antwoord 1, Autoriteit 100%

In ASP.NET MVC4 De standaard JavaScript-serializer die wordt gebruikt in de JsonResultKlasse is nog steeds de Javascriptserizer (u kunt het controleren in de CODE )

Ik denk dat je het hebt verward met de ASP.NET Web.API, waar JSON.net de standaard JS Serializer is, maar MVC4 gebruikt het niet.

Dus je moet JSON.net configureren om met MVC4 te werken (eigenlijk moet je je eigen JsonNetResult) maken, er zijn er genoeg artikelen over:

Als u ook JSON.net wilt gebruiken voor controlleractieparameters, dus tijdens de modelbinding, dan hebt u uw eigen ValueProviderFactoryImplementation nodig.

en u moet uw implementatie registreren met:

ValueProviderFactories.Factories
    .Remove(ValueProviderFactories.Factories
                                  .OfType<JsonValueProviderFactory>().Single());
ValueProviderFactories.Factories.Add(new MyJsonValueProviderFactory());

U kunt de ingebouwde JsonValueProviderFactoryals een voorbeeld of dit artikel gebruiken: ASP.NET MVC 3 – Verbeterde JSONVALUEPROVIDERFACTORY met JSON.net


Antwoord 2, Autoriteit 7%

ASP.NET MVC 5-fix:

Ik was nog niet klaar om te veranderen in JSON.net, maar in mijn geval dat de fout tijdens het verzoek optreedt. De beste aanpak in mijn scenario modificeerde de werkelijke JsonValueProviderFactorydie de fix toepast op het wereldwijde project en kan worden gedaan door de global.csbestand als zodanig te bewerken.

JsonValueProviderConfig.Config(ValueProviderFactories.Factories);

Voeg een web.config invoer toe:

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

en maak vervolgens de twee volgende klassen

public class JsonValueProviderConfig
{
    public static void Config(ValueProviderFactoryCollection factories)
    {
        var jsonProviderFactory = factories.OfType<JsonValueProviderFactory>().Single();
        factories.Remove(jsonProviderFactory);
        factories.Add(new CustomJsonValueProviderFactory());
    }
}

Dit is eigenlijk een exacte kopie van de standaardimplementatie die is gevonden in System.Web.Mvc, maar met de toevoeging van een configureerbare web.config-appseerwaarde 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;
    }
}

Other episodes