【问题标题】:How to construct the payload for Web API PATCH Method?如何为 Web API PATCH 方法构建有效负载?
【发布时间】:2021-01-20 10:01:27
【问题描述】:

我有一个用 .NET Core 编写的 Web API。

PATCH方法在参数中使用[FromBody]JsonPatchDocument:

[HttpPatch("{id}")]
public Account Patch(int id, [FromBody]JsonPatchDocument<Account> accountPath)

我能够从 Postman 或 Swagger UI 执行所有方法(GET、PUT、POST、PATCH),但我在从 .NET 客户端应用程序执行 PATCH 方法时遇到了困难。

这是我在 Swagger UI 或 Postman 上为 PATCH 方法传递给请求正文的内容:

[{"op": "replace","path": "/Name","value": "Test111"}]

如何在 .NET 客户端应用程序中传递上述有效负载?

当我执行以下代码时,它不会给我一个错误,但响应是

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:

这是我的代码:

using System.Net.Http;
using Newtonsoft.Json;

using (var client = new HttpClient(handler))
{
   var AccountPayload = new Dictionary<string, object>
   {
      {"Name", "TEST111"}
   };
   var content = JsonConvert.SerializeObject(AccountPayload);
   var request = new HttpRequestMessage(new HttpMethod("PATCH"), "https://localhost:5001/api/myAPI/1");
   request.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/json");
   HttpResponseMessage response = await client.SendAsync(request);
   var responseString = await response.Content.ReadAsStringAsync();
   return response; //--> response = StatusCode: 400, ReasonPhrase: 'Bad Request'
}

谢谢。

【问题讨论】:

  • [{"op": "replace","path": "/Name","value": "Test111"}]是一个对象数组,在这个例子中,数组中的一个对象有3个属性:oppathvalue,你的AccountPayload不匹配这种类型的json。所以它可能无法反序列化您在客户端中发送的json
  • 正确。如何为 Web API 创建此数组有效负载?

标签: c# json .net asp.net-web-api asp.net-core-webapi


【解决方案1】:

过去也遇到过补丁问题。在我的情况下,这些是通过 X-Http-Method-Override 标头解决的:

        if (request.Method == Method.PATCH)
        {
            request.AddHeader("X-Http-Method-Override", "PATCH");
            request.Method = Method.POST;
        }

【讨论】:

    【解决方案2】:

    您可以使用Microsoft.AspNetCore.JsonPatch nuget 包中的JsonPatchDocument&lt;T&gt; 来构建补丁

    var patchDoc = new JsonPatchDocument<Account>();
    patchDoc.Replace(p => p.Name, "TEST111");
    Console.WriteLine(JsonConvert.SerializeObject(patchDoc)); // outputs what you'd expect
    

    这假设您将Account 类(具有Name 属性)作为客户端上的强类型对象。如果没有,可以按如下方式使用非泛型变体:

    var patchDoc = new JsonPatchDocument();
    patchDoc.Replace("/Name", "TEST111");
    Console.WriteLine(JsonConvert.SerializeObject(patchDoc));
    

    【讨论】:

      【解决方案3】:

      由于您的问题似乎是如何为客户端创建此有效负载以传递给您的 api,因此我建议使用模型类来表示您的有效负载:

      //Model class to represent one object in payload
      public class MyPayload
      {
          [JsonProperty("op")]
          public string Op {get; set;}
          
          [JsonProperty("path")]
          public string Path {get; set;}
          
          [JsonProperty("value")]
          public string Value {get; set;}
      }
      

      然后在您的示例代码中,更改为:

      var AccountPayload = new List<MyPayload>
      {
         new MyPayload() { Op = "replace", Path = "/Name", Value = "Test111" }
      };
      

      【讨论】:

      • 这是可能的,但 JsonPatchDocument 具有创建内置补丁的功能。
      【解决方案4】:

      我会尝试使用 JObject 而不是 JsonPatchDocument

      【讨论】:

      • Ryan Wilson 的建议有效。非常感谢大家!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-22
      • 1970-01-01
      • 2014-12-21
      相关资源
      最近更新 更多