JSON在Web Api操作中无法正确绑定

时间:2014-09-04 21:57:00

标签: c# asp.net-mvc asp.net-web-api

我正在使用asp.net webapi创建和api 出于某些原因,这个json:

JSON => {"page":"1","count":"10","sorting[name]":"asc"}
JSONString = >"{\"page\":\"1\",\"count\":\"10\",\"sorting[name]\":\"asc\"}"

没有正确地将bindend传递给这样的模型:

 public class DataSourceRequestParams
    {
        public int Page { get; set; }
        public int Count { get; set; }
        public IDictionary<string, string> Sorting { get; set; }
        public IDictionary<string, string> Filter { get; set; }
        public IDictionary<string, string> Order { get; set; }
    }

Sorting属性没有绑定。

[HttpPost]
        public PagingResult<ApplicationUser> Get([FromBody] DataSourceRequestParams @params)
        {...}

如果我在MVC应用程序中创建一个动作并传递相同的JSON,它就会被绑定。

我在这里遗漏了什么吗?

1 个答案:

答案 0 :(得分:1)

当Content-Type为application / json时,Web API中的绑定需要Dictionary作为JSON对象,因此以下JSON将与您的模型正确绑定:

{"page":"1","count":"10","sorting":{"name":"asc"}}

修改

如果您无法更改传入的JSON,则需要手动将JSON绑定到对象。这里有几个选择。您可以编写自己的IModelBinder,也可以通过编写自己的JsonConverter来覆盖JSON活页夹的行为。

作为一个粗略的例子,您可以像这样创建一个JsonConverter

public class DictionaryConverter : JsonConverter
{
    public DictionaryConverter()
    {
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        //I've not implemented writing the Json
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        //create a new object
        var temp = new DataSourceRequestParams();

        temp.Sorting = new Dictionary<string, string>();
        temp.Filter = new Dictionary<string, string>();
        temp.Order = new Dictionary<string, string>();

        //load the input into a JObject and grab the "simple" values
        JObject jsonObject = JObject.Load(reader);
        temp.Page = jsonObject["page"].Value<int>();
        temp.Count = jsonObject["count"].Value<int>();

        //parse the dictionary values
        AddValuesToDictionary(temp, jsonObject, "sorting", temp.Sorting);
        AddValuesToDictionary(temp, jsonObject, "filter", temp.Filter);
        AddValuesToDictionary(temp, jsonObject, "order", temp.Order);

        return temp;
    }

    private void AddValuesToDictionary(DataSourceRequestParams test, JObject jsonObject, string name, IDictionary<string, string> dictionary)
    {
        //grab each matching property
        var properties = jsonObject.Properties().Where(j => j.Name.StartsWith(name));
        if (properties != null)
        {
            foreach (var property in properties)
            {
                /*for each matched property grab the value between the brackets 
                 * from the name and the property value
                 * and the associate json value and add it to the dictionary
                 */
                dictionary.Add(Regex.Match(property.Name, @"\[([^\]]*)\]").Groups[1].Value, property.Value.Value<string>());                    
            }
        }
    }

    public override bool CanConvert(Type objectType)
    {
        //we can convert if the type is DataSourceRequestParams
        return typeof(DataSourceRequestParams).IsAssignableFrom(objectType);
    }
}

然后在GlobalConfiguration中注册新转换器:

GlobalConfiguration.Configuration.Formatters.JsonFormatter
     .SerializerSettings.Converters.Add(new DictionaryConverter());

然后您的原始JSON将正确解析。显然,代码没有所有错误处理等,所以它不是生产准备好的。