Подтвердить что ты не робот

Установка стандартного JSON-сериализатора в ASP.NET MVC

Я работаю над существующим приложением, которое было частично преобразовано в MVC. Всякий раз, когда контроллер отвечает с помощью JSON ActionResult, перечисления отправляются как числа, противоположные имени строки. Похоже, что по умолчанию последовательный сериализатор должен быть JSON.Net, который должен посылать перечисления как их имена, противоположные целочисленному представлению, но это не так.

Мне не хватает настройки web.config, которая устанавливает это как сериализатор по умолчанию? Или есть другой параметр, который необходимо изменить?

4b9b3361

Ответ 1

В ASP.Net MVC4 по умолчанию сериализатор JavaScript по умолчанию, который используется в классе JsonResult, по-прежнему является JavaScriptSerializer (вы можете проверить это в code)

Я думаю, вы запутали его с ASP.Net Web.API, где JSON.Net является стандартным JS-сериализатором, но MVC4 не использует его.

Итак, вам нужно настроить JSON.Net для работы с MVC4 (в основном вам нужно создать свой собственный JsonNetResult), есть много статей об этом:

Если вы также хотите использовать JSON.Net для параметров действия контроллера, поэтому во время привязки модели вам нужно написать собственную реализацию ValueProviderFactory.

И вам нужно зарегистрировать свою реализацию с помощью:

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

Вы можете использовать встроенный JsonValueProviderFactory в качестве примера или этой статьи: ASP.NET MVC 3 - Улучшено JsonValueProviderFactory с помощью Json.Net

Ответ 2

ASP.NET MVC 5 Fix:

Я еще не был готов перейти на Json.NET, и в моем случае ошибка возникала во время запроса. Наилучшим подходом в моем сценарии было изменение фактического JsonValueProviderFactory который применяет исправление к глобальному проекту и может быть выполнено путем редактирования файла global.cs как такового.

JsonValueProviderConfig.Config(ValueProviderFactories.Factories);

добавьте запись web.config:

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

а затем создать два следующих класса

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

Это в основном точная копия реализации по умолчанию, найденная в System.Web.Mvc но с добавлением настраиваемого значения aspnet:MaxJsonLength для настройки 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;
    }
}