developer tip

ASP.NET MVC에서 기본 JSON serializer 설정

optionbox 2020. 12. 31. 08:12
반응형

ASP.NET MVC에서 기본 JSON serializer 설정


부분적으로 MVC로 변환 된 기존 응용 프로그램에서 작업 중입니다. 컨트롤러가 JSON ActionResult로 응답 할 때마다 열거 형은 문자열 이름이 아닌 숫자로 전송됩니다. 기본 시리얼 라이저가 JSON.Net이어야하는 것처럼 들리는데, 정수 표현과 반대되는 이름으로 열거 형을 보내야하지만 여기에서는 그렇지 않습니다.

이것을 기본 직렬 변환기로 설정하는 web.config 설정이 누락 되었습니까? 아니면 변경해야하는 다른 설정이 있습니까?


ASP.Net MVC4에서 JsonResult클래스에 사용되는 기본 JavaScript serializer 는 여전히 JavaScriptSerializer입니다 ( 코드 에서 확인할 수 있음 ).

JSON.Net이 기본 JS serializer이지만 MVC4는 사용하지 않는 ASP.Net Web.API와 혼동했다고 생각합니다.

따라서 MVC4와 함께 작동하도록 JSON.Net을 구성해야합니다 (기본적으로 직접 생성해야 함 JsonNetResult). 이에 대한 많은 기사가 있습니다.

컨트롤러 작업 매개 변수에 JSON.Net을 사용하려는 경우 모델 바인딩 중에 자체 ValueProviderFactory구현을 작성해야합니다 .

그리고 다음과 같이 구현을 등록해야합니다.

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

내장 된 JsonValueProviderFactory예제 또는이 문서를 사용할 수 있습니다 . ASP.NET MVC 3 – Json.Net을 사용하여 향상된 JsonValueProviderFactory


ASP.NET MVC 5 수정 :

아직 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이지만 구성 가능한 web.config appsetting 값이 추가 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;
    }
}

참조 URL : https://stackoverflow.com/questions/14591750/setting-the-default-json-serializer-in-asp-net-mvc

반응형