【问题标题】:How to detect duplicate keys in Web Api Post request Json如何检测 Web Api Post 请求 Json 中的重复键
【发布时间】:2016-06-18 02:50:40
【问题描述】:

当请求 Json 包含重复键时,我需要从 ASP.NET Web API Post 请求返回 400 错误。

例如,如果请求是

{
   "key1": "value1",
   "key2": 1000,
   "key2": 2000,
   "key3": "value3"
}

那么我希望由于有两个“key2”键而引发错误。

我的控制器方法看起来像

[HttpPost]
public IHttpActionResult PostMethod([FromBody]RequestModel request)
{
   .....
}

和我的 RequestModel 模型一样

public class RequestModel
{
    [Required]
    public string Key1 {get; set; }

    [Required]
    public int Key2 {get; set; }

    public string Key3 {get; set; } 
}

在上面的示例中,Json 序列化程序似乎很乐意接受请求并使用 2000 填充 Key2,或者任何密钥的最后一个实例。

我想我需要做一些涉及 JsonSerializerSettings 类的事情,或者实现一个自定义 JsonConverter,但是我不确定如何继续。

【问题讨论】:

    标签: c# json asp.net-web-api json.net deserialization


    【解决方案1】:

    这是一个自定义 JsonConverter,当遇到 Asp.Net Web API 应自动处理的重复键时,它会抛出代码为 400 的 HttpResponseException。

    class DuplicateJsonConverter : JsonConverter
    {
        public override bool CanWrite { get { return false; } }
    
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var paths = new HashSet<string>();
            existingValue = existingValue ?? Activator.CreateInstance(objectType, true);
    
            var backup = new StringWriter();
    
            using (var writer = new JsonTextWriter(backup))
                do
                {
                    writer.WriteToken(reader.TokenType, reader.Value);
    
                    if (reader.TokenType != JsonToken.PropertyName)
                        continue;
    
                    if (string.IsNullOrEmpty(reader.Path))
                        continue;
    
                    if (paths.Contains(reader.Path))
                           throw new HttpResponseException(HttpStatusCode.BadRequest); //as 400
    
                    paths.Add(reader.Path);
                }
                while (reader.Read());
    
            JsonConvert.PopulateObject(backup.ToString(), existingValue);
            return existingValue;
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    你应该使用这个转换器来装饰你的 RequestModel 类。

    [JsonConverter(typeof(DuplicateJsonConverter))]
    class RequestModel
    {
      \\...
    }
    

    【讨论】:

      【解决方案2】:

      您可以创建一个拦截DelegateHandler,它会在您每次收到请求时触发。在其中,您可以获得发送到控制器的数据并检查它是否有重复的键。 创建的处理程序是这样注册的:

      GlobalConfiguration.Configuration.MessageHandlers.Add(new YourDelegateHandler());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-30
        • 1970-01-01
        • 2013-09-12
        • 1970-01-01
        • 2021-03-19
        相关资源
        最近更新 更多