如何使用JSON。NET作为ASP的模型绑定器。净MVC控制器吗?

时间:2021-09-23 06:52:11

It has been decided by the ASP.NET Web API team to use the JSON.NET library for model binding JSON data. However, "normal" MVC controllers still use the inferior JsonDataContractSerializer. This causes issues with parsing dates, and is causing me much headache.

这是由ASP决定的。NET Web API团队使用JSON。用于绑定JSON数据的模型库。然而,“普通”MVC控制器仍然使用劣质的JsonDataContractSerializer。这导致解析日期出现问题,并使我非常头痛。

See this for reference:
http://www.devcurry.com/2013/04/json-dates-are-different-in-aspnet-mvc.html

请参阅:http://www.devcurry.com/2013/04/jsons -are- difference -aspnet-mvc.html

The author chooses to solve the issue in the Knockout layer on the client. But I would prefer to solve this by using the same JSON.NET model binder in MVC controllers as in Web API controllers.

作者选择在客户端的淘汰层中解决这个问题。但我更愿意使用相同的JSON来解决这个问题。NET模型绑定器在MVC控制器中就像在Web API控制器中一样。

How do I substitute a different JSON model binder into ASP.NET MVC? Specifically, the JSON.NET library. Using the same model binder from Web API would be ideal if possible.

如何将不同的JSON模型绑定器替换为ASP。净MVC吗?具体来说,JSON。网络图书馆。如果可能的话,使用来自Web API的相同模型绑定器是理想的。

2 个解决方案

#1


6  

I have done this, and also heavily customized the serialization that Json.NET is doing, by:

我已经这样做了,并且对Json的序列化进行了大量的定制。净,:

Replace the default formatter in global.asax.cs, Application_Start:

替换global.asax中的默认格式化程序。cs,Application_Start:

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
GlobalConfiguration.Configuration.Formatters.Add(new CustomJsonMediaTypeFormatter());

And my CustomJsonMediaTypeFormatter is:

我的观点是:CustomJsonMediaTypeFormatter

public static class CustomJsonSettings
{
    private static JsonSerializerSettings _settings;

    public static JsonSerializerSettings Instance
    {
        get
        {
            if (_settings == null)
            {
                var settings = new JsonSerializerSettings();

                // Must convert times coming from the client (always in UTC) to local - need both these parts:
                settings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal }); // Critical part 1
                settings.DateTimeZoneHandling = DateTimeZoneHandling.Local;   // Critical part 2

                // Skip circular references
                settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

                // Handle special cases in json (self-referencing loops, etc)
                settings.ContractResolver = new CustomJsonResolver();

                _settings = settings;
            }

            return _settings;
        }
    }
}

public class CustomJsonMediaTypeFormatter : MediaTypeFormatter
{
    public JsonSerializerSettings _jsonSerializerSettings;

    public CustomJsonMediaTypeFormatter()
    {
        _jsonSerializerSettings = CustomJsonSettings.Instance;

        // Fill out the mediatype and encoding we support
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        SupportedEncodings.Add(new UTF8Encoding(false, true));
    }

    public override bool CanReadType(Type type)
    {
        return true;
    }

    public override bool CanWriteType(Type type)
    {
        return true;
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task reading the content
        return Task.Factory.StartNew(() =>
        {
            using (StreamReader streamReader = new StreamReader(stream, SupportedEncodings.First()))
            {
                using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                {
                    return serializer.Deserialize(jsonTextReader, type);
                }
            }
        });
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task writing the serialized content
        return Task.Factory.StartNew(() =>
        {
            using (StreamWriter streamWriter = new StreamWriter(stream, SupportedEncodings.First()))
            {
                using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
                {
                    serializer.Serialize(jsonTextWriter, value);
                }
            }
        });
    }
}

And finally, the CustomJsonResolver:

最后,CustomJsonResolver:

public class CustomJsonResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
    {
        var list = base.CreateProperties(type, memberSerialization);

        // Custom stuff for my app
        if (type == typeof(Foo))
        {
            RemoveProperty(list, "Bar");
            RemoveProperty(list, "Bar2");
        }

        return list;
    }

    private void RemoveProperty(IList<JsonProperty> list, string propertyName)
    {
        var rmc = list.FirstOrDefault(x => x.PropertyName == propertyName);

        if (rmc != null)
        {
            list.Remove(rmc);
        }
    }
}

#2


0  

The JsonNetValueProviderFactory proposed here works better than the others I've tried (I had issues with arrays using Greg Ennis' one for example). This link also propose a solution to return Json from an action.

这里建议的JsonNetValueProviderFactory比我尝试过的其他版本工作得更好(例如,我在使用Greg Ennis的数组时遇到了问题)。这个链接还提出了一个从操作返回Json的解决方案。

#1


6  

I have done this, and also heavily customized the serialization that Json.NET is doing, by:

我已经这样做了,并且对Json的序列化进行了大量的定制。净,:

Replace the default formatter in global.asax.cs, Application_Start:

替换global.asax中的默认格式化程序。cs,Application_Start:

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
GlobalConfiguration.Configuration.Formatters.Add(new CustomJsonMediaTypeFormatter());

And my CustomJsonMediaTypeFormatter is:

我的观点是:CustomJsonMediaTypeFormatter

public static class CustomJsonSettings
{
    private static JsonSerializerSettings _settings;

    public static JsonSerializerSettings Instance
    {
        get
        {
            if (_settings == null)
            {
                var settings = new JsonSerializerSettings();

                // Must convert times coming from the client (always in UTC) to local - need both these parts:
                settings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal }); // Critical part 1
                settings.DateTimeZoneHandling = DateTimeZoneHandling.Local;   // Critical part 2

                // Skip circular references
                settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

                // Handle special cases in json (self-referencing loops, etc)
                settings.ContractResolver = new CustomJsonResolver();

                _settings = settings;
            }

            return _settings;
        }
    }
}

public class CustomJsonMediaTypeFormatter : MediaTypeFormatter
{
    public JsonSerializerSettings _jsonSerializerSettings;

    public CustomJsonMediaTypeFormatter()
    {
        _jsonSerializerSettings = CustomJsonSettings.Instance;

        // Fill out the mediatype and encoding we support
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        SupportedEncodings.Add(new UTF8Encoding(false, true));
    }

    public override bool CanReadType(Type type)
    {
        return true;
    }

    public override bool CanWriteType(Type type)
    {
        return true;
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task reading the content
        return Task.Factory.StartNew(() =>
        {
            using (StreamReader streamReader = new StreamReader(stream, SupportedEncodings.First()))
            {
                using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                {
                    return serializer.Deserialize(jsonTextReader, type);
                }
            }
        });
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext)
    {
        // Create a serializer
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task writing the serialized content
        return Task.Factory.StartNew(() =>
        {
            using (StreamWriter streamWriter = new StreamWriter(stream, SupportedEncodings.First()))
            {
                using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
                {
                    serializer.Serialize(jsonTextWriter, value);
                }
            }
        });
    }
}

And finally, the CustomJsonResolver:

最后,CustomJsonResolver:

public class CustomJsonResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
    {
        var list = base.CreateProperties(type, memberSerialization);

        // Custom stuff for my app
        if (type == typeof(Foo))
        {
            RemoveProperty(list, "Bar");
            RemoveProperty(list, "Bar2");
        }

        return list;
    }

    private void RemoveProperty(IList<JsonProperty> list, string propertyName)
    {
        var rmc = list.FirstOrDefault(x => x.PropertyName == propertyName);

        if (rmc != null)
        {
            list.Remove(rmc);
        }
    }
}

#2


0  

The JsonNetValueProviderFactory proposed here works better than the others I've tried (I had issues with arrays using Greg Ennis' one for example). This link also propose a solution to return Json from an action.

这里建议的JsonNetValueProviderFactory比我尝试过的其他版本工作得更好(例如,我在使用Greg Ennis的数组时遇到了问题)。这个链接还提出了一个从操作返回Json的解决方案。