I have a requirement to return a 400 error from an ASP.NET Web API Post request when the request Json contains duplicate keys.
For instance if the request was
{
   "key1": "value1",
   "key2": 1000,
   "key2": 2000,
   "key3": "value3"
}
then I would want the error to be thrown due to there being two "key2" keys.
My controller method looks something like
[HttpPost]
public IHttpActionResult PostMethod([FromBody]RequestModel request)
{
   .....
}
and my RequestModel model like
public class RequestModel
{
    [Required]
    public string Key1 {get; set; }
    [Required]
    public int Key2 {get; set; }
    public string Key3 {get; set; } 
}
In the example above the Json serializer seems happy to accept the request and populate Key2 with 2000, or whatever the last instance of the key is.
I am thinking I need to do something involving the JsonSerializerSettings class, or implement a custom JsonConverter, however I am unsure how to proceed.
Here is a custom JsonConverter which throws an HttpResponseException with code 400 when encounters to a duplicated key which Asp.Net Web API should automatically handle it.
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();
    }
}
and you should decorate your RequestModel class using this converter.
[JsonConverter(typeof(DuplicateJsonConverter))]
class RequestModel
{
  \\...
}
                        You can create an intercepting DelegateHandler which will fire every time you get a request. In it you can get the data which is sent to your controller and check if it has duplicate keys. Created handler is registered like this:
GlobalConfiguration.Configuration.MessageHandlers.Add(new YourDelegateHandler());
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With