System.Web.Http.ApiController дает нулевой параметр при сбое десериализации

У меня есть настраиваемая реализация JsonConverter для класса, который передается в качестве параметра остаточному методу POST.

При определенных обстоятельствах JsonConverter вызовет исключение. Когда это происходит, вызывается остальной метод POST с нулевым значением для объекта, а не 500, возвращаемым клиенту, как я ожидал. Это означает, что я не могу сообщить клиенту значимую ошибку.

Как я могу изменить или обойти это поведение?

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
    }
  }
}

person DJL    schedule 18.03.2016    source источник
comment
Используйте CheckModelForNullAttribute из strathweb.com/2012/10/   -  person maxbeaudoin    schedule 18.03.2016
comment
Я думаю, вы могли неправильно понять мой вопрос там @maxbeaudoin   -  person DJL    schedule 18.03.2016
comment
Именно так я решаю проблему, которую вы описываете. Я проверяю нулевую модель и возвращаю клиенту осмысленное сообщение. Есть несколько сценариев, в которых модель может быть нулевой. Это одна из них. Вот как можно обойти это поведение.   -  person maxbeaudoin    schedule 18.03.2016
comment
проблема заключается в обнаружении того, что не удалось выполнить десериализацию. Я хотел знать, ПОЧЕМУ это не удалось. Смотрите мой ответ ниже.   -  person DJL    schedule 18.03.2016


Ответы (1)


На основе этого ответа у меня есть обходной путь https://stackoverflow.com/a/32950529/1273906 Каждый класс API имеет ModelState, которое содержит, среди прочего, любое исключение, возникшее во время десериализации.

Итак, я создал этот метод в своем базовом классе api:

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);
  }
}

поэтому простого вызова CheckForDeserializationErrors() в качестве первой строки любого метода API достаточно, чтобы повторно выбросить любые ошибки десериализации.

person DJL    schedule 18.03.2016