Search code examples
c#.netjson.netjson-deserializationasp.net-apicontroller

System.Web.Http.ApiController gives null parameter when deserialization fails


I have a custom JsonConverter implementation for a class which is passed as a parameter to a rest POST method.

Under certain circumstances the JsonConverter will throw an exception. When this happens the rest POST method is invoked with a null value for the object, rather than a 500 being returned to the client as I would expect. This means I cannot supply a meaningful error to the client.

How can I change or workaround this behaviour?

using System.Web.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MyControllers
{
  class MyConverter: JsonConverter
  {
...
      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
        throw new Exception("You can't do that");
      }
   }
  [JsonConverter(typeof(MyConverter))]
  public class MyClass
  {
...
  }
  public class MyController : ApiController
  {
    public string Post([FromBody]MyClass MyObject)
    {
      // Method is invoked with null value for MyObject
    }
  }
}

Solution

  • Based on this answer I have a workaround https://stackoverflow.com/a/32950529/1273906 Each API class has a ModelState property which contains, among other things, any exception that were raised during deserialization.

    So I have now created this method on my api base class:

    protected void CheckForDeserializationErrors()
    {
      foreach (Exception ex in ModelState.SelectMany(v => v.Value.Errors.Select(e => e.Exception)))
      {
        throw new Newtonsoft.Json.JsonException(ex.Message, ex);
      }
    }
    

    so a simple call to CheckForDeserializationErrors() as the first line of any API method is sufficient to re-throw any deserialization errors