Как предоставить пользовательское связующее для модели для свойства модели из тела? - PullRequest
0 голосов
/ 07 декабря 2018

У меня проблемы с написанием пользовательского связывателя модели для службы веб-API ASP.NET Core 2.1.У меня есть метод действия, подобный следующему:

public async Task<IActionResult> SaveAccountEvents([FromRoute] Guid accountId, IList<AccountEvent> events)
{
}

Класс AccountEvent имеет множество свойств, включая

[BindProperty(BinderType = typeof(CustomBinding))]
public string EventBody { get; set; }

Цель состоит в том, чтобы я хотел, чтобы значение этого свойства было получено от клиентабыть либо строкой, либо объектом JObject (JSON).Идея состоит в том, что клиент может отправлять строковый JSON или JSON в EventBody, и модель будет хранить его в виде строки - в конечном итоге в виде строкового JSON.

Проблема, с которой я сталкиваюсь, заключается в том, что в моей пользовательской привязке bindingContext.ValueProvider.GetValue никогда ничего не возвращает.Глядя на имущество, оно содержит только RouteValueProvider.Я не вижу способа, которым я мог бы извлечь ценности из тела.Существуют ли другие способы настройки десериализации JSON в ASP.NET Core Web API?

Обновление:

Этот API-интерфейс используется клиентами для отправки данных о событиях.Данные события состоят из конверта, который содержит такие вещи, как имя события, дата отправки, пользователь, который инициировал событие, и т. Д. В текущей версии фактические данные события отправляются в виде строкового JSON.Итак, прямо сейчас запрос будет выглядеть (тело события уведомления - строка):

{
  "eventDate": "20180909",
  "eventBody": "{
      \"newLastName\": \"bob\",
      \"primaryApplication\": \"bob\"
    }"
}

Изменение состоит в том, что я хочу принимать тело события в виде JSON.В этом случае клиент должен иметь возможность отправлять (обратите внимание, что тело события является правильным JSON):

{
  "eventDate": "20180909",
  "eventBody": {
    "newLastName": "bob",
    "primaryApplication": "bob"
  }
}

Оба эти сценария должны поддерживаться, и существующий API является строковой версией.Я пытаюсь настроить API так, чтобы, если отправляемое событие представляло собой объект JSON, оно было структурировано в модели, поступающей в Action.

1 Ответ

0 голосов
/ 08 декабря 2018

Спасибо Кирку за указание на решение.В итоге я вообще пропустил привязку модели (ура!) И смог добиться того, что мне было нужно, с помощью специального сериализатора с атрибутом в свойстве: [JsonConverter(typeof(EventBodyJsonConverter))].Имея это, я могу использовать [FromBody] в действии, чтобы получить привязку к содержимому.

public class EventBodyJsonConverter : JsonConverter
{
    private JsonSerializer _jsonSerializer;

    public EventBodyJsonConverter()
    {
        _jsonSerializer = new JsonSerializer();
    }

    public override bool CanConvert(Type objectType) => objectType == typeof(string);

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            var eventJObject = _jsonSerializer.Deserialize<JObject>(reader);
            return eventJObject.ToString();
        }

        if (reader.TokenType == JsonToken.String)
        {
            return reader.Value.ToString();
        }

        throw new Exception();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {

    }
}
...