wake-up-neo.net

Festlegen des Standard-JSON-Serializers in ASP.NET MVC

Ich arbeite an einer vorhandenen Anwendung, die teilweise in MVC konvertiert wurde. Wenn ein Controller mit einem JSON-ActionResult antwortet, werden die Aufzählungen als Zahlen gesendet, die dem Namen der Zeichenfolge nicht entsprechen. Der Standard-Serialisierer sollte JSON.Net lauten. Dies sollte JSON.Net sein, das die Enummen als Namen senden sollte, die nicht der Ganzzahldarstellung entsprechen. Dies ist jedoch nicht der Fall.

Fehlt mir eine web.config-Einstellung, die dies als Standard-Serializer festlegt? Oder gibt es eine andere Einstellung, die geändert werden muss?

55
John

In ASP.Net MVC4 ist der Standard-JavaScript-Serializer, der in der JsonResult-Klasse verwendet wird, immer noch der JavaScriptSerializer (Sie können ihn im code prüfen.)

Ich denke, Sie haben es mit der ASP.Net-Web.API verwechselt, wobei JSON.Net der Standard-JS-Serialisierer ist, MVC4 es jedoch nicht verwendet.

Sie müssen JSON.Net so konfigurieren, dass es mit MVC4 funktioniert (im Wesentlichen müssen Sie Ihre eigene JsonNetResult erstellen). Dazu gibt es viele Artikel:

Wenn Sie JSON.Net auch für Controller-Aktionsparameter verwenden möchten, müssen Sie während der Modellbindung eine eigene ValueProviderFactory-Implementierung schreiben. 

Und Sie müssen Ihre Implementierung bei registrieren: 

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

Sie können die integrierte JsonValueProviderFactory als Beispiel oder in diesem Artikel verwenden: ASP.NET MVC 3 - Verbesserte JsonValueProviderFactory mit Json.Net

71
nemesv

ASP.NET MVC 5-Fix:

Ich war noch nicht bereit, zu Json.NET zu wechseln, und in meinem Fall trat der Fehler während der Anfrage auf. Der beste Ansatz in meinem Szenario bestand darin, die tatsächliche JsonValueProviderFactory zu ändern, die das Update auf das globale Projekt anwendet. Dies kann durch Bearbeiten der global.cs-Datei erfolgen.

JsonValueProviderConfig.Config(ValueProviderFactories.Factories);

fügen Sie einen web.config-Eintrag hinzu:

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

und erstellen Sie dann die beiden folgenden Klassen

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

Dies ist im Grunde eine exakte Kopie der Standardimplementierung in System.Web.Mvc, jedoch zusätzlich mit dem konfigurierbaren web.config-Wert für die Einstellung 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