【问题标题】:400 Bad Request submitting Json to WebApi via HttpClient.PutAsync400 Bad Request 通过 HttpClient.PutAsync 向 WebApi 提交 Json
【发布时间】:2019-02-06 17:22:04
【问题描述】:

通常,从服务到 webapi 调用都会使用序列化对象,但在这种情况下,我必须使用 json 表示来进行调用。

该过程是将 json 反序列化为适当的类,然后照常处理。

HttpClient 放

从控制台应用程序中调用方法

   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] 标记,则会命中端点,但正如预期的那样,该参数为空。似乎发生了某种过滤。

    [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": []
    }
  }

【问题讨论】:

  • 如果它没有到达你的端点,它可能是路由,我看到你的方法上有一个空的 Route 属性,你的控制器类上有路由前缀吗?
  • [FromBody] 将尝试反序列化到给定的对象 - 在你的情况下是一个字符串..你可以输入 ([FromBody] JObject payment) - 这将防止你需要反序列化对象。转换为对象你可以做payment.ToObject&lt;&gt;()
  • @CallumLinington 请给我一个答案,这样我就可以“检查它” - 做到了!!!
  • @WillLopez 完成!

标签: c# json asp.net-core-webapi dotnet-httpclient


【解决方案1】:

只是扩展我的评论。

OP 做到了:

[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>();

【讨论】:

    【解决方案2】:

    您的有效负载不是字符串,而是 json,这就是运行时无法将正文解析为您请求的 string paymentSyncJson 的原因。

    要解决这个问题,请创建一个反映 json 的匹配 dto

    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)
    

    【讨论】:

    • 感谢您的回复,但上面的 cmets 中有答案。通常这就是我的工作方式并且效果很好......在这种情况下,这是系统之间的互操作问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多