简体   繁体   English

400错误的请求,通过HttpClient.PutAsync将Json提交到WebApi

[英]400 Bad Request submitting Json to WebApi via HttpClient.PutAsync

Normally, serialized objects would be used from the services to the webapi calls but in this instance I have to use a json representation for the call. 通常,从服务到webapi调用都将使用序列化的对象,但是在这种情况下,我必须为调用使用json表示形式。

The process would be to deserialize the json to the proper class, then process as usual. 该过程将是将json反序列化为适当的类,然后照常进行处理。

HttpClient Put HttpClient放

Method is called from within a console app 从控制台应用程序中调用方法

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

        ... 
    }

Endpoint 终点

The call never hits the endpoint. 呼叫永远不会到达端点。 The endpoint is hit if I remove the [FromBody] tag but as expected, the parameter is null. 如果删除[FromBody]标记,则端点被命中,但是按预期,该参数为null。 There seems to be some sort of filtering happening. 似乎正在发生某种过滤。

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

This is the json payload. 这是json负载。 I thought [FromBody] took care of simple types but this is proving me wrong. 我以为[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": []
    }
  }

Your payload is not a string, it's a json, that's why the runtime can't parse the body to your requested string paymentSyncJson . 您的有效负载不是字符串,而是json,这就是运行时无法将主体解析为您请求的string paymentSyncJson

To solve it, create a matching dto which reflects the json 要解决此问题,请创建一个反映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; }
}

Then use it in the controller method to read the data from the request body 然后在控制器方法中使用它从请求主体中读取数据

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

Just expanding on my Comment. 只是扩大我的评论。

The OP did: 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);
   ....
}

Where they have put [FromBody] string paymentSyncJson , FromBody will try and deserialise into the type you specify, in this case string . 在他们将[FromBody] string paymentSyncJson放入的[FromBody] string paymentSyncJson ,FromBody会尝试反序列化为您指定的类型,在这种情况下为string I suggest doing: 我建议这样做:

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

Then you can change this line: 然后,您可以更改此行:

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

To: 至:

var paymentSync = paymentSyncJson.ToObject<PaymentSync>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM