如何在MVC5项目中使用Json.NET为JSON modelbinding? [英] How to use Json.NET for JSON modelbinding in an MVC5 project?

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

问题描述

我一直期待在互联网的答案或例子,但没能找到呢。我只是想改变这是用来反序列化JSON而modelbinding到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.

我发现<一个href=\"http://stackoverflow.com/questions/20980241/how-do-i-sub-in-json-net-as-model-binder-for-asp-net-mvc-controllers\">this SO发布,但不能执行它,到目前为止,我甚至不能看到 System.Net.Http.Formatters 命名空间,我也能看到 GlobalConfiguration

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).

解决方案是使用自定义值提供程序工厂。这里需要对code。

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 方法中使用这样的:

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

这里是向我指出了正确的方向后,和<一个href=\"http://haacked.com/archive/2011/06/30/whatrsquos-the-difference-between-a-value-provider-and-model-binder.aspx/\">also这个了价值提供商和modelbinders一个很好的解释。

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 modelbinding?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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