如何在 MVC5 项目中使用 Json.NET 进行 JSON 模型绑定? [英] How to use Json.NET for JSON modelbinding in an MVC5 project?

查看:19
本文介绍了如何在 MVC5 项目中使用 Json.NET 进行 JSON 模型绑定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在互联网上寻找答案或示例,但还没有找到.我只是想更改默认的 JSON 序列化器,该序列化器用于在模型绑定到 JSON.NET 库时反序列化 JSON.

I've been looking around the internet for an answer or example, but could not find one yet. I simply would like to change the default JSON serializer which is used to deserialize JSON while modelbinding to JSON.NET library.

我发现 this SO 帖子,但到目前为止无法实现,我什至看不到 System.Net.Http.Formatters 命名空间,也看不到 全局配置.

I've found this SO post, but cannot implement it so far, I can't even see the System.Net.Http.Formatters namespace, nor can I see GlobalConfiguration.

我错过了什么?

更新

我有一个 ASP.NET MVC 项目,它基本上是一个 MVC3 项目.目前我的目标是 .NET 4.5 并使用 ASP.NET MVC 5 和相关的 NuGet 包.

I have an ASP.NET MVC project, it was basically an MVC3 project. Currently I'm targetting .NET 4.5 and using the ASP.NET MVC 5 and related NuGet packages.

我没有看到 System.Web.Http 程序集,也没有看到任何类似的命名空间.在这种情况下,我想注入 JSON.NET 作为 JSON 类型请求的默认模型绑定器.

I don't see the System.Web.Http assembly, nor any similar namespace. In this context I would like to inject JSON.NET to be used as the default model binder for JSON type of requests.

推荐答案

我终于找到了答案.基本上我不需要 MediaTypeFormatter 的东西,它不是为在 MVC 环境中使用而设计的,但在 ASP.NET Web API 中,这就是为什么我看不到那些引用和命名空间(顺便说一句,这些都包含在 Microsoft.AspNet.WeApi NuGet 包中).

I've finally found an answer. Basically I don't need the MediaTypeFormatter stuff, that's not designed to be used in MVC environment, but in ASP.NET Web APIs, that's why I do not see those references and namespaces (by the way, those are included in the Microsoft.AspNet.WeApi NuGet package).

解决方案是使用自定义值提供程序工厂.这是所需的代码.

The solution is to use a custom value provider factory. Here is the code required.

    public class JsonNetValueProviderFactory : ValueProviderFactory
    {
        public override IValueProvider GetValueProvider(ControllerContext controllerContext)
        {
            // first make sure we have a valid context
            if (controllerContext == null)
                throw new ArgumentNullException("controllerContext");

            // now make sure we are dealing with a json request
            if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
                return null;

            // get a generic stream reader (get reader for the http stream)
            var streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
            // convert stream reader to a JSON Text Reader
            var JSONReader = new JsonTextReader(streamReader);
            // tell JSON to read
            if (!JSONReader.Read())
                return null;

            // make a new Json serializer
            var JSONSerializer = new JsonSerializer();
            // add the dyamic object converter to our serializer
            JSONSerializer.Converters.Add(new ExpandoObjectConverter());

            // use JSON.NET to deserialize object to a dynamic (expando) object
            Object JSONObject;
            // if we start with a "[", treat this as an array
            if (JSONReader.TokenType == JsonToken.StartArray)
                JSONObject = JSONSerializer.Deserialize<List<ExpandoObject>>(JSONReader);
            else
                JSONObject = JSONSerializer.Deserialize<ExpandoObject>(JSONReader);

            // create a backing store to hold all properties for this deserialization
            var backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
            // add all properties to this backing store
            AddToBackingStore(backingStore, String.Empty, JSONObject);
            // return the object in a dictionary value provider so the MVC understands it
            return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
        }

        private static void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, object value)
        {
            var d = value as IDictionary<string, object>;
            if (d != null)
            {
                foreach (var entry in d)
                {
                    AddToBackingStore(backingStore, MakePropertyKey(prefix, entry.Key), entry.Value);
                }
                return;
            }

            var l = value as IList;
            if (l != null)
            {
                for (var i = 0; i < l.Count; i++)
                {
                    AddToBackingStore(backingStore, MakeArrayKey(prefix, i), l[i]);
                }
                return;
            }

            // primitive
            backingStore[prefix] = value;
        }

        private static string MakeArrayKey(string prefix, int index)
        {
            return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
        }

        private static string MakePropertyKey(string prefix, string propertyName)
        {
            return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName;
        }
    }

你可以在你的 Application_Start 方法中像这样使用它:

And you can use it like this in your Application_Start method:

// remove default implementation    
ValueProviderFactories.Factories.Remove(ValueProviderFactories.Factories.OfType<JsonValueProviderFactory>().FirstOrDefault());
// add our custom one
ValueProviderFactories.Factories.Add(new JsonNetValueProviderFactory());

这里是给我指明正确方向的帖子,也是这个 对价值提供者和模型绑定器.

Here is the post which pointed me to the right direction, and also this one gave a good explanation on value providers and modelbinders.

这篇关于如何在 MVC5 项目中使用 Json.NET 进行 JSON 模型绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆