Définir le serializer JSON par défaut dans ASP.NET MVC

je travaille sur une application existante qui a été partiellement convertie en MVC. Chaque fois qu'un controller répond avec un JSON ActionResult, les enums sont envoyés sous forme de nombres par opposition au nom de la chaîne. Il semble que le serializer par défaut devrait être JSON.Net, qui devraient envoyer les enum comme leurs noms opposés à la représentation entière, mais ce n'est pas le cas ici.

est-ce qu'il me manque une toile.paramètre de configuration qui définit ceci comme la valeur par défaut sérialiseur? Ou est-il un autre paramètre qui doit être changé?

55
demandé sur Stephen Kennedy 2013-01-30 00:35:42

2 réponses

In ASP.Net MVC4 le serializer JavaScript par défaut qui est utilisé dans la classe JsonResult est toujours le JavaScriptSerializer (vous pouvez le vérifier dans le code )

je pense que vous l'avez confondu avec le ASP.Net Web.IPA où JSON.Net est le serializer js par défaut mais MVC4 ne l'utilise pas.

donc vous devez configurer JSON.Net pour travailler avec MVC4 (en gros, vous devez créer votre propre JsonNetResult ), Il ya beaucoup d'articles à ce sujet:

si vous voulez également utiliser JSON.Net pour les paramètres d'action du contrôleur, pendant la liaison du modèle, vous devez donc écrire votre propre implémentation ValueProviderFactory .

et vous devez enregistrer votre implémentation avec:

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

vous pouvez utiliser le construit dans JsonValueProviderFactory comme un exemple ou cet article: ASP.NET MVC 3-Improved JsonValueProviderFactory using Json.Net

70
répondu nemesv 2017-05-23 12:10:38

ASP.NET fixation MVC 5:

Je n'étais pas prêt à changer pour Json.NET juste pour l'instant et dans mon cas, l'erreur se produisait pendant la requête. La meilleure approche dans mon scénario était de modifier le JsonValueProviderFactory qui applique le correctif au projet global et qui peut être fait en éditant le fichier global.cs comme tel.

JsonValueProviderConfig.Config(ValueProviderFactories.Factories);

ajouter un web.entrée de configuration:

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

et puis créer les deux classes suivantes

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

il s'agit essentiellement d'une copie exacte de l'implémentation par défaut trouvée dans System.Web.Mvc mais avec l'ajout d'un web configurable.config appsetting valeur 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
répondu Maxim Gershkovich 2018-06-03 11:08:29