400 неверных запросов на отправку Json в WebApi через HttpClient.PutAsync - PullRequest
0 голосов
/ 06 февраля 2019

Как правило, сериализованные объекты используются из сервисов для вызовов webapi, но в этом случае у меня есть для использования представления json для вызова.

Процесс будет состоять в десериализацииjson в соответствующий класс, затем обработайте как обычно.

HttpClient Put

Метод вызывается из консольного приложения

   public async Task<ApiMessage<string>> PutAsync(Uri baseEndpoint, string relativePath, Dictionary<string, string> headerInfo, string json)
    {
        HttpClient httpClient = new HttpClient();
        if (headerInfo != null)
        {
            foreach (KeyValuePair<string, string> _header in headerInfo)
                _httpClient.DefaultRequestHeaders.Add(_header.Key, _header.Value);
        }

        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json-patch+json"));

        var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");

        var response = await httpClient.PutAsync(CreateRequestUri(relativePath, baseEndpoint), content);
        var data = await response.Content.ReadAsStringAsync();

        ... 
    }

Конечная точка

Вызов никогда не достигнет конечной точки.Конечная точка удаляется, если я удаляю тег [FromBody], но, как и ожидалось, параметр имеет значение null.Кажется, что происходит какая-то фильтрация.

    [HttpPut()]
    [Route("")]
    [SwaggerResponse(StatusCodes.Status200OK)]
    [SwaggerResponse(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> UpdatePaymentSync([FromBody] string paymentSyncJson)
    {
        if (string.IsNullOrEmpty(paymentSyncJson))
            return BadRequest();
         //hack: don't have access to models so need to send json rep
         var paymentSync = JsonConvert.DeserializeObject<PaymentSync>(paymentSyncJson);
       ....
    }

Это полезная нагрузка json.Я думал, что [FromBody] позаботился о простых типах, но это доказывает, что я не прав.

  {
    "paymentSyncJson": {
      "id": 10002,
      "fileName": "Empty_20190101.csv",
      "comments": "Empty File",
      "processingDate": "2019-01-02T19:43:11.373",
      "status": "E",
      "createdDate": "2019-01-02T19:43:11.373",
      "createdBy": "DAME",
      "modifiedDate": null,
      "modifiedBy": null,
      "paymentSyncDetails": []
    }
  }

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Просто расширив мой комментарий.

ОП сделал:

[HttpPut()]
[Route("")]
[SwaggerResponse(StatusCodes.Status200OK)]
[SwaggerResponse(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UpdatePaymentSync([FromBody] string paymentSyncJson)
{
    if (string.IsNullOrEmpty(paymentSyncJson))
        return BadRequest();
     //hack: don't have access to models so need to send json rep
     var paymentSync = JsonConvert.DeserializeObject<PaymentSync>(paymentSyncJson);
   ....
}

Куда они поместили [FromBody] string paymentSyncJson, FromBody попытается десериализовать в указанный вами тип, в данном случаеstring.Я предлагаю сделать:

public async Task<IActionResult> UpdatePaymentSync([FromBody] JObject paymentSyncJson)

Затем вы можете изменить эту строку:

var paymentSync = JsonConvert.DeserializeObject<PaymentSync>(paymentSyncJson);

Кому:

var paymentSync = paymentSyncJson.ToObject<PaymentSync>();
0 голосов
/ 06 февраля 2019

Ваша полезная нагрузка - не строка, это json, поэтому среда выполнения не может проанализировать тело к вашему запросу string paymentSyncJson.

Чтобы решить эту проблему, создайте соответствующий dto, который отражает json

public class PaymentDto
{
    public PaymentSyncDto PaymentSyncJson { get; set; }
}
public class PaymentSyncDto
{
    public int Id { get; set; }
    public string FileName { get; set; }
    public string Comments { get; set; }
    public DateTime ProcessingDate { get; set; }
    public string Status { get; set; }
    public DateTime CreatedDate { get; set; }
    public string CreatedBy { get; set; }
    public DateTime ModifiedDate { get; set; }
    public string ModifiedBy { get; set; }
    public int[] PaymentSyncDetails { get; set; }
}

Затем используйте его в методе контроллера для чтения данных из тела запроса

public async Task<IActionResult> UpdatePaymentSync([FromBody] PaymentDto payment)
...