使用 JsonPatchDocument 和动态对象问题的 HttpPatch 操作

HttpPatch operation with JsonPatchDocument and dynamic objects issue

努力解决以下问题,使用这个例子:

https://github.com/dotnet/AspNetCore.Docs/blob/8793347c90ba83166c0efc6cb5fbae60a0e063a7/aspnetcore/web-api/jsonpatch/samples/3.1/api/Controllers/HomeController.cs

我有一个带有补丁操作的控制器,它以参数 a

JsonPatchDocument patch

然后几乎将补丁应用到类似于示例的动态(expando)对象

patch.ApplyTo(obj);

但不幸的是 ApplyTo(obj) 死于以下错误:

StatusCode = 500, Message = For operation 'replace', the target location specified by path '/updateuser/value' was not found

将您的运算符从“替换”更改为“添加”。

试试这个:

Json 示例:

[
  {
    "op": "add",
    "path": "/updateuser",
    "value": {
      "orderName": "Order2",
      "orderType": null
    }
  }
]

和动作:

    [HttpPatch]
    public IActionResult JsonPatchWithModelState([FromBody]JsonPatchDocument patch)
    {
        dynamic obj = new ExpandoObject();

        patch.ApplyTo(obj);

        return Ok(obj);
    }

        

您发送的操作json中的路径不是url-path,而是您目标实体的属性。

替换:

{"op":"replace","path":"/updateuser/value","value":"12345"}

与:

{ "op": "replace", "path": "propertyname", "value": "propertyvalue" }

场景:

假设我们有一个会议站点,与会者想要更新他们之前给演讲者的评论。在这种情况下,我们有一个与会者想要更新的评论 object,在这里我们只需要更新评论部分,所以让我们使用 JSON 补丁来执行此任务。

有多种方法可以执行补丁操作。这里有两种简单的方法。

发送 JsonPatchDocument object 作为参数 在运行时创建 JsonPatchDocument 我们将在本文中看到这两种方法。现在让我们看一些代码。

我在 SpeakerController 中创建了“PatchReview”动作,并用 [HTTPPATCH] 属性装饰它。

   [Route("api/[controller]")]
    public class SpeakerController : Controller
    {
        [HttpPatch("{reviewId}")]
        public IActionResult PatchReview([FromBody] JsonPatchDocument<SpeakerReview> patchDocument)
        {
            if (patchDocument == null)
            {
                return BadRequest();
            }
            //In your application get speaker review object from database base on review Id
            var speakerFromDb = new SpeakerReview { ReviewId = 2, SpeakerId = 101, Rate = 2.5M, Review = "Good speaker.", ReviewDate = DateTime.UtcNow.AddDays(-1)};
 
            //Apply changes to speaker object
            patchDocument.ApplyTo(speakerFromDb);
 
            //update speaker in database and return updated object
            return Ok(speakerFromDb);
        }
    }

此方法从请求 body 接受 JsonPatchDocument 类型的 parameter/object,然后我们将获得需要根据请求的 reviewId 更新的实际评论 object 但出于演示目的,我们是创建虚拟 SpeakerReview object,我们假设它是一个实际的 object 并将补丁应用于 object,最后 return 更新评论。实际上,一个场景会有所不同,例如测试空条件,修补后保存评论等..

第二种方法:

在上面的操作中,我传递了一个实际的 JsonPatchDocument object 作为参数,所以你需要记住补丁文档的实际格式,但如果你不想记住这些格式,那么你可以使用内置在相应的操作方法中在运行时创建JsonPatchDocument。

让我们看一个第二种方法的例子。如果你深入研究 JsonPatchDocument class 有 Replace 方法,你必须在其中传递路径,即 SpeakerReview object 的目标 property/properties 和新值然后它将 return JsonPatchDocument object 相当于您作为第一种方法的参数传递的 object 。现在您可以在 ApplyTo 方法的帮助下将该补丁文档应用于目标 object。所有 JSON 补丁操作都可以创建 JsonPatchDocument object.

//Creating JsonPatchDocument
        //Result: [{"op":"replace", "path":"/review", "value":"Good Speaker. I like presentation Style."}]
        var jsonPatch = new JsonPatchDocument<SpeakerReview>().Replace(x => x.Review, "Good Speaker. I like presentation Style.");
 
        //In your application get speaker review object from database base on review Id
        var speakerFromDb = new SpeakerReview
        {
            ReviewId = 2,
            SpeakerId = 101,
            Rate = 2.5M,
            Review = "Good speaker.",
            ReviewDate = DateTime.UtcNow.AddDays(-1)
        };
 
        //Apply changes to speaker object
        jsonPatch.ApplyTo(speakerFromDb);
 
        //update speaker in database and return updated object
        return Ok(speakerFromDb);

补丁逻辑就这些了。让我们看看如何从 POSTMAN 中调用这个 API:

Note: This step is valid only if you used the first technique.

将请求类型更改为 PATCH 并在 body 中准备 JSON object。确保它是 JSON 补丁文件格式。在这里,我们只替换审查,所以我在操作数组中传递单个操作 object,但你可以传递多个操作,它将按顺序执行。

所以基本上有了这个 JSON 补丁文件,我发送了一个命令来用新值替换评论的旧值 属性。

提示:确保您的补丁请求 header 包含 Content-Type of “application/json-patch+json” MIME,否则您的请求将以 415 Unsupported Media Type 状态结束代码。

让我们将 BreakPoint 放入补丁操作中并点击发送按钮。

在这里您可以比较旧的和新修补的 SpeakerReview object 的评论 属性 的价值。在实际应用程序中,现在您需要执行剩余的任务,但我在这里 return 更新 object。

您可以尝试第二种方法,结果与上述相同。

这是更新的 SpeakerReview object 作为回应。

就是这样。这就是我们如何在 AspNet Core 应用程序中实现 JSON 补丁。在开始使用 JSON 补丁(最多需要 30 分钟)之前,至少阅读一次 JSON 补丁规范将是很好的第一步。您可以在规范的最后找到不同操作的非常好的示例。

我希望这可以帮助您开始使用 JSON AspNet Core 中的补丁。