{"id":246,"date":"2023-10-15T15:36:38","date_gmt":"2023-10-15T07:36:38","guid":{"rendered":"https:\/\/miie.net\/?p=246"},"modified":"2023-10-15T15:36:38","modified_gmt":"2023-10-15T07:36:38","slug":"ultimate-asp-net-core-web-api-chapter12-working-with-patch-requests","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=246","title":{"rendered":"Chapter12:WORKING WITH PATCH REQUESTS"},"content":{"rendered":"<h1>12 WORKING WITH PATCH REQUESTS<\/h1>\n<p>In the previous chapter, we worked with the PUT request to fully update our resource. But if we want to update our resource only partially, we should use PATCH.<br \/>\n\u5728\u4e0a\u4e00\u7ae0\u4e2d\uff0c\u6211\u4eec\u4f7f\u7528 PUT \u8bf7\u6c42\u6765\u5b8c\u5168\u66f4\u65b0\u6211\u4eec\u7684\u8d44\u6e90\u3002\u4f46\u662f\uff0c\u5982\u679c\u6211\u4eec\u53ea\u60f3\u90e8\u5206\u66f4\u65b0\u6211\u4eec\u7684\u8d44\u6e90\uff0c\u6211\u4eec\u5e94\u8be5\u4f7f\u7528 PATCH\u3002<\/p>\n<\/p>\n<p>The partial update isn\u2019t the only difference between PATCH and PUT. The request body is different as well. For the Company PATCH request, for example, we should use <strong>[FromBody]JsonPatchDocument<Company><\/strong> and not <strong>[FromBody]Company<\/strong> as we did with the PUT requests.<br \/>\n\u90e8\u5206\u66f4\u65b0\u5e76\u4e0d\u662fPATCH\u548cPUT\u4e4b\u95f4\u7684\u552f\u4e00\u533a\u522b\u3002\u8bf7\u6c42\u6b63\u6587\u4e5f\u4e0d\u540c\u3002\u4f8b\u5982\uff0c\u5bf9\u4e8e\u516c\u53f8\u8865\u4e01\u8bf7\u6c42\uff0c\u6211\u4eec\u5e94\u8be5\u4f7f\u7528 [FromBody]JsonPatchDocument<Company>\u800c\u4e0d\u662f\u50cf\u5904\u7406 PUT \u8bf7\u6c42\u90a3\u6837\u4f7f\u7528 [FromBody]Company\u3002<\/p>\n<p>Additionally, for the PUT request\u2019s media type, we have used <strong>application\/json<\/strong> \u2014 but for the PATCH request\u2019s media type, we should use <strong>application\/json-patch+json<\/strong>. Even though the first one would be accepted in ASP.NET Core for the PATCH request, the recommendation by REST standards is to use the second one.<br \/>\n\u6b64\u5916\uff0c\u5bf9\u4e8e PUT \u8bf7\u6c42\u7684\u5a92\u4f53\u7c7b\u578b\uff0c\u6211\u4eec\u4f7f\u7528\u4e86 application\/json \u2014 \u4f46\u5bf9\u4e8e PATCH \u8bf7\u6c42\u7684\u5a92\u4f53\u7c7b\u578b\uff0c\u6211\u4eec\u5e94\u8be5\u4f7f\u7528 application\/json-patch+json\u3002 \u5c3d\u7ba1\u7b2c\u4e00\u4e2a ASP.NET Core\u4f1a\u63a5\u53d7\u7528\u4e8ePATCH\u8bf7\u6c42\uff0c\u4f46REST\u6807\u51c6\u7684\u5efa\u8bae\u662f\u4f7f\u7528\u7b2c\u4e8c\u4e2a\u3002<\/p>\n<p>Let\u2019s see what the PATCH request body looks like:<br \/>\n\u8ba9\u6211\u4eec\u770b\u770b PATCH \u8bf7\u6c42\u6b63\u6587\u662f\u4ec0\u4e48\u6837\u5b50\u7684\uff1a<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\n&#x5B; \n    {\n         &quot;op&quot;: &quot;replace&quot;,\n         &quot;path&quot;: &quot;\/name&quot;, \n        &quot;value&quot;: &quot;new name&quot; \n    }, \n    { \n        &quot;op&quot;: &quot;remove&quot;, \n        &quot;path&quot;: &quot;\/name&quot; \n    } \n]\n\n<\/pre>\n<\/p>\n<p>The square brackets represent an array of operations. Every operation is placed between curly brackets. So, in this specific example, we have two operations: Replace and Remove represented by the op property. The path property represents the object\u2019s property that we want to modify and the value property represents a new value.<br \/>\n\u65b9\u62ec\u53f7\u8868\u793a\u64cd\u4f5c\u6570\u7ec4\u3002\u6bcf\u4e2a\u64cd\u4f5c\u90fd\u653e\u5728\u5927\u62ec\u53f7\u4e4b\u95f4\u3002\u56e0\u6b64\uff0c\u5728\u8fd9\u4e2a\u7279\u5b9a\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u6709\u4e24\u4e2a\u64cd\u4f5c\uff1a\u66ff\u6362\u548c\u5220\u9664\u7531 op \u5c5e\u6027\u8868\u793a\u3002path \u5c5e\u6027\u8868\u793a\u6211\u4eec\u8981\u4fee\u6539\u7684\u5bf9\u8c61\u5c5e\u6027\uff0cvalue \u5c5e\u6027\u8868\u793a\u65b0\u503c\u3002<\/p>\n<p>In this specific example, for the first operation, we replace the value of the name property to a new name. In the second example, we remove the name property, thus setting its value to default.<br \/>\n\u5728\u6b64\u7279\u5b9a\u793a\u4f8b\u4e2d\uff0c\u5bf9\u4e8e\u7b2c\u4e00\u4e2a\u64cd\u4f5c\uff0c\u6211\u4eec\u5c06 name \u5c5e\u6027\u7684\u503c\u66ff\u6362\u4e3a\u65b0\u540d\u79f0\u3002\u5728\u7b2c\u4e8c\u4e2a\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5220\u9664 name \u5c5e\u6027\uff0c\u4ece\u800c\u5c06\u5176\u503c\u8bbe\u7f6e\u4e3a\u9ed8\u8ba4\u503c\u3002<\/p>\n<p>There are six different operations for a PATCH request:<br \/>\n\u5bf9\u4e8e PATCH \u8bf7\u6c42\uff0c\u6709\u516d\u79cd\u4e0d\u540c\u7684\u64cd\u4f5c\uff1a<\/p>\n<table>\n<tr>\n<th>\nOPERATION\n<\/th>\n<th>\nREQUEST BODY\n<\/th>\n<th>\nEXPLANATION\n<\/th>\n<\/tr>\n<tr>\n<td>\nAdd\n<\/td>\n<td>\n{<br \/>\n    \"op\": \"add\",<br \/>\n    \"path\": \"\/name\",<br \/>\n    \"value\": \"new value\"<br \/>\n}\n<\/td>\n<td>\nAssigns a new value to a required property.<br \/>\n\u4e3a\u5fc5\u9700\u5c5e\u6027\u5206\u914d\u65b0\u503c\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nRemove\n<\/td>\n<td>\n{<br \/>\n    \"op\": \"remove\",<br \/>\n    \"path\": \"\/name\"<br \/>\n}\n<\/td>\n<td>\nSets a default value to a required property.<br \/>\n\u5c06\u9ed8\u8ba4\u503c\u8bbe\u7f6e\u4e3a\u5fc5\u9700\u5c5e\u6027\n<\/td>\n<\/tr>\n<tr>\n<td>\nReplace\n<\/td>\n<td>\n{<br \/>\n    \"op\": \"replace\",<br \/>\n    \"path\": \"\/name\",<br \/>\n    \"value\": \"new value\"<br \/>\n}\n<\/td>\n<td>\nReplaces a value of a required property to a new value.<br \/>\n\u5c06\u5fc5\u9700\u5c5e\u6027\u7684\u503c\u66ff\u6362\u4e3a\u65b0\u503c\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nCopy\n<\/td>\n<td>\n{<br \/>\n    \"op\": \"copy\",<br \/>\n    \"from\": \"\/name\",<br \/>\n    \"path\": \"\/title\"<br \/>\n}\n<\/td>\n<td>\nCopies the value from a property in the \u201cfrom\u201d part to the property in the \u201cpath\u201d part.<br \/>\n\u5c06\u503c\u4ece\u201cfrom\u201d\u90e8\u5206\u4e2d\u7684\u5c5e\u6027\u590d\u5236\u5230\u201cpath\u201d\u90e8\u5206\u4e2d\u7684\u5c5e\u6027\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nMove\n<\/td>\n<td>\n{<br \/>\n    \"op\": \"move\",<br \/>\n    \"from\": \"\/name\",<br \/>\n    \"path\": \"\/title\"<br \/>\n}\n<\/td>\n<td>\nMoves the value from a property in the \u201cfrom\u201d part to a property in the \u201cpath\u201d part.<br \/>\n\u5c06\u503c\u4ece\u201cfrom\u201d\u90e8\u5206\u4e2d\u7684\u5c5e\u6027\u79fb\u52a8\u5230\u201cpath\u201d\u90e8\u5206\u4e2d\u7684\u5c5e\u6027\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nTest\n<\/td>\n<td>\n{<br \/>\n    \"op\": \"test\",<br \/>\n    \"path\": \"\/name\",<br \/>\n    \"value\": \"new value\"<br \/>\n}\n<\/td>\n<td>\nTests if a property has a specified value.<br \/>\n\u6d4b\u8bd5\u5c5e\u6027\u662f\u5426\u5177\u6709\u6307\u5b9a\u7684\u503c\u3002\n<\/td>\n<\/tr>\n<\/table>\n<p>After all this theory, we are ready to dive into the coding part.<br \/>\n\u5728\u6240\u6709\u8fd9\u4e9b\u7406\u8bba\u4e4b\u540e\uff0c\u6211\u4eec\u51c6\u5907\u6df1\u5165\u7814\u7a76\u7f16\u7801\u90e8\u5206\u3002<\/p>\n<h2>12.1 Applying PATCH to the Employee Entity<\/h2>\n<p>Before we start with the controller modification, we have to install two required libraries:<br \/>\n\u5728\u5f00\u59cb\u4fee\u6539\u63a7\u5236\u5668\u4e4b\u524d\uff0c\u6211\u4eec\u5fc5\u987b\u5b89\u88c5\u4e24\u4e2a\u5fc5\u9700\u7684\u5e93\uff1a<\/p>\n<ul>\n<li>\nThe Microsoft.AspNetCore.JsonPatch library to support the usage of JsonPatchDocument in our controller and<br \/>\nMicrosoft.AspNetCore.JsonPatch \u5e93\uff0c\u652f\u6301\u5728\u6211\u4eec\u7684\u63a7\u5236\u5668\u4e2d\u4f7f\u7528 JsonPatchDocument \u548c\n<\/li>\n<li>\nThe Microsoft.AspNetCore.Mvc.NewtonsoftJson library to support request body conversion to a PatchDocument once we send our request.<br \/>\nMicrosoft.AspNetCore.Mvc.NewtonsoftJson \u5e93\uff0c\u652f\u6301\u5728\u6211\u4eec\u53d1\u9001\u6211\u4eec\u7684\u8bf7\u6c42\u6b63\u6587\u540e\u8f6c\u6362\u4e3a PatchDocument\u8bf7\u6c42\u3002\n<\/li>\n<\/ul>\n<p>As you can see, we are still using the NewtonsoftJson library to support the PatchDocument conversion in .NET 5. The official statement from Microsoft is that they are not going to replace it with System.Text.Json: <em>\u201cThe main reason is that this will require a huge investment from us, with not a very high value-add for majority of our customers.\u201d.<\/em><br \/>\n\u5982\u60a8\u6240\u89c1\uff0c\u6211\u4eec\u4ecd\u5728\u4f7f\u7528 NewtonsoftJson \u5e93\u6765\u652f\u6301 .NET 5 \u4e2d\u7684 PatchDocument \u8f6c\u6362\u3002Microsoft\u7684\u5b98\u65b9\u58f0\u660e\u662f\uff0c\u4ed6\u4eec\u4e0d\u4f1a\u7528System.Text.Json\u53d6\u4ee3\u5b83\uff1a\u201c\u4e3b\u8981\u539f\u56e0\u662f\u8fd9\u5c06\u9700\u8981\u6211\u4eec\u7684\u5de8\u989d\u6295\u8d44\uff0c\u5305\u62ec\u5bf9\u4e8e\u6211\u4eec\u7684\u5927\u591a\u6570\u5ba2\u6237\u6765\u8bf4\uff0c\u8fd9\u4e0d\u662f\u4e00\u4e2a\u5f88\u9ad8\u7684\u9644\u52a0\u503c\u3002<\/p>\n<p>Once the installation is completed, we have to add the NewtonsoftJson configuration to IServiceCollection:<br \/>\n\u5b89\u88c5\u5b8c\u6210\u540e\uff0c\u6211\u4eec\u5fc5\u987b\u6dfb\u52a0 NewtonsoftJson\u914d\u7f6e\u5230 IServiceCollection\uff1a<\/p>\n<p><pre class=\"brush: csharp; highlight: [5]; title: ; notranslate\" title=\"\">\nservices.AddControllers(config =&gt;\n{\n    config.RespectBrowserAcceptHeader = true;\n    config.ReturnHttpNotAcceptable = true;\n}).AddNewtonsoftJson()\n.AddXmlDataContractSerializerFormatters()\n.AddCustomCSVFormatter();\n<\/pre>\n<\/p>\n<p>Add it before the Xml and CSV formatters. Now we can continue.<br \/>\n\u5c06\u5176\u6dfb\u52a0\u5230 XML \u548c CSV \u683c\u5f0f\u5316\u7a0b\u5e8f\u4e4b\u524d\u3002\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u7ee7\u7eed\u4e86\u3002<\/p>\n<p>We will require a mapping from the Employee type to the EmployeeForUpdateDto type. Therefore, we have to create a mapping rule for that.<br \/>\n\u6211\u4eec\u9700\u8981\u4ece\u201c\u5458\u5de5\u201d\u7c7b\u578b\u6620\u5c04\u5230\u201c\u5458\u5de5\u66f4\u65b0Dto\u201d\u7c7b\u578b\u7684\u6620\u5c04\u3002\u56e0\u6b64\uff0c\u6211\u4eec\u5fc5\u987b\u4e3a\u6b64\u521b\u5efa\u4e00\u4e2a\u6620\u5c04\u89c4\u5219\u3002<\/p>\n<p>If we take a look at the MappingProfile class, we will see that we have a mapping from the EmployeeForUpdateDto to the Employee type:<br \/>\n\u5982\u679c\u6211\u4eec\u770b\u4e00\u4e0b MappingProfile \u7c7b\uff0c\u6211\u4eec\u5c06\u770b\u5230\u6211\u4eec\u6709\u4e00\u4e2a\u4ece EmployeeForUpdateDto \u5230 Employee \u7c7b\u578b\u7684\u6620\u5c04\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nCreateMap&lt;EmployeeForUpdateDto, Employee&gt;();\n<\/pre>\n<\/p>\n<p>But we need it another way. To do so, we are not going to create an additional rule; we can just use the ReverseMap method to help us in the process:<br \/>\n\u4f46\u6211\u4eec\u9700\u8981\u53e6\u4e00\u79cd\u65b9\u5f0f\u3002\u4e3a\u6b64\uff0c\u6211\u4eec\u4e0d\u4f1a\u521b\u5efa\u5176\u4ed6\u89c4\u5219;\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 ReverseMap \u65b9\u6cd5\u6765\u5e2e\u52a9\u6211\u4eec\u5b8c\u6210\u8fd9\u4e2a\u8fc7\u7a0b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nCreateMap&lt;EmployeeForUpdateDto, Employee&gt;().ReverseMap();\n<\/pre>\n<\/p>\n<p>The ReverseMap method is also going to configure this rule to execute reverse mapping if we ask for it.<br \/>\n\u5982\u679c\u6211\u4eec\u8981\u6c42\uff0cReverseMap \u65b9\u6cd5\u8fd8\u5c06\u914d\u7f6e\u6b64\u89c4\u5219\u4ee5\u6267\u884c\u53cd\u5411\u6620\u5c04\u3002<\/p>\n<p>Now, we can modify our controller:<br \/>\n\u73b0\u5728\uff0c\u6211\u4eec\u53ef\u4ee5\u4fee\u6539\u6211\u4eec\u7684\u63a7\u5236\u5668\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/EmployeesController.cs\n\n&#x5B;HttpPatch(&quot;{id}&quot;)]\npublic IActionResult PartiallyUpdateEmployeeForCompany(Guid companyId, Guid id, &#x5B;FromBody] JsonPatchDocument&lt;EmployeeForUpdateDto&gt; patchDoc)\n{\n    if (patchDoc == null)\n    {\n        _logger.LogError(&quot;patchDoc object sent from client is null.&quot;);\n        return BadRequest(&quot;patchDoc object is null&quot;);\n    }\n    var company = _repository.Company.GetCompany(companyId, trackChanges: false);\n    if (company == null)\n    {\n        _logger.LogInfo($&quot;Company with id: {companyId} doesn&#039;t exist in the database.&quot;);\n        return NotFound();\n    }\n    var employeeEntity = _repository.Employee.GetEmployee(companyId, id, trackChanges: true);\n    if (employeeEntity == null)\n    {\n        _logger.LogInfo($&quot;Employee with id: {id} doesn&#039;t exist in the database.&quot;);\n        return NotFound();\n    }\n    var employeeToPatch = _mapper.Map&lt;EmployeeForUpdateDto&gt;(employeeEntity);\n    patchDoc.ApplyTo(employeeToPatch);\n    _mapper.Map(employeeToPatch, employeeEntity);\n    _repository.Save();\n    return NoContent();\n}\n<\/pre>\n<\/p>\n<p>You can see that our action signature is different from the PUT actions. We are accepting the JsonPatchDocument from the request body. After that, we have a familiar code where we check the patchDoc for null value and if the company and employee exist in the database. Then, we map from the Employee type to the EmployeeForUpdateDto type; it is important for us to do that because the patchDoc variable can apply only to the EmployeeForUpdateDto type. After apply is executed, we map again to the Employee type (from employeeToPatch to employeeEntity) and save changes in the database.<br \/>\n\u60a8\u53ef\u4ee5\u770b\u5230\u6211\u4eec\u7684\u64cd\u4f5c\u7b7e\u540d\u4e0e PUT \u64cd\u4f5c\u4e0d\u540c\u3002\u6211\u4eec\u6b63\u5728\u63a5\u53d7\u6765\u81ea\u8bf7\u6c42\u6b63\u6587\u7684 JsonPatchDocument\u3002\u4e4b\u540e\uff0c\u6211\u4eec\u6709\u4e00\u4e2a\u719f\u6089\u7684\u4ee3\u7801\uff0c\u6211\u4eec\u5728\u5176\u4e2d\u68c0\u67e5 patchDoc \u7684\u7a7a\u503c\u4ee5\u53ca\u6570\u636e\u5e93\u4e2d\u662f\u5426\u5b58\u5728\u516c\u53f8\u548c\u5458\u5de5\u3002\u7136\u540e\uff0c\u6211\u4eec\u4ece\u5458\u5de5\u7c7b\u578b\u6620\u5c04\u5230\u5458\u5de5\u66f4\u65b0Dto\u7c7b\u578b;\u8fd9\u6837\u505a\u5bf9\u6211\u4eec\u6765\u8bf4\u5f88\u91cd\u8981\uff0c\u56e0\u4e3a patchDoc \u53d8\u91cf\u53ea\u80fd\u5e94\u7528\u4e8e EmployeeForUpdateDto \u7c7b\u578b\u3002\u6267\u884c\u5e94\u7528\u540e\uff0c\u6211\u4eec\u6620\u5c04\u518d\u6b21\u5230\u5458\u5de5\u7c7b\u578b\uff08\u4ece\u5458\u5de5\u5230\u8865\u4e01\u5230employeeEntity\uff09\uff0c\u5e76\u5c06\u66f4\u6539\u4fdd\u5b58\u5728\u6570\u636e\u5e93\u4e2d\u3002<\/p>\n<p>Now, we can send a couple of requests to test this code:<br \/>\n\u73b0\u5728\uff0c\u6211\u4eec\u53ef\u4ee5\u53d1\u9001\u51e0\u4e2a\u8bf7\u6c42\u6765\u6d4b\u8bd5\u6b64\u4ee3\u7801\uff1a<\/p>\n<p>Let\u2019s first send the replace operation:<br \/>\n\u8ba9\u6211\u4eec\u9996\u5148\u53d1\u9001\u66ff\u6362\u64cd\u4f5c\uff1a<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n&#x5B;\n    {\n        &quot;op&quot;:&quot;replace&quot;,\n        &quot;path&quot;:&quot;\/age&quot;,\n        &quot;value&quot;:&quot;28&quot;\n    }\n]\n<\/pre>\n<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\">https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D<\/a><\/a><\/a>- 4B20-B5DE-024705497D4A<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1201.jpg\" alt=\"Alt text\" \/><\/p>\n<p>It works; we get the 204 No Content message. Let\u2019s check the same employee:<br \/>\n\u5b83\u6709\u6548;\u6211\u4eec\u6536\u5230 204 \u65e0\u5185\u5bb9\u6d88\u606f\u3002\u8ba9\u6211\u4eec\u68c0\u67e5\u540c\u4e00\u4e2a\u5458\u5de5\uff1a<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\">https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D<\/a><\/a><\/a>- 4B20-B5DE-024705497D4A<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1203.jpg\" alt=\"Alt text\" \/><\/p>\n<p>And we see the Age property has been changed.<br \/>\n\u6211\u4eec\u770b\u5230 Age \u5c5e\u6027\u5df2\u66f4\u6539\u3002<\/p>\n<p>Let\u2019s send a remove operation in a request:<br \/>\n\u8ba9\u6211\u4eec\u5728\u8bf7\u6c42\u4e2d\u53d1\u9001\u5220\u9664\u64cd\u4f5c\uff1a<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n&#x5B;\n    {\n        &quot;op&quot;:&quot;remove&quot;,\n        &quot;path&quot;:&quot;\/age&quot;\n    }\n]\n<\/pre>\n<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\">https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D<\/a><\/a><\/a>- 4B20-B5DE-024705497D4A<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1204.jpg\" alt=\"Alt text\" \/><\/p>\n<p>This works as well. Now, if we check our employee, its age is going to be set to 0 (the default value for the int type):<br \/>\n\u8fd9\u4e5f\u884c\u5f97\u901a\u3002\u73b0\u5728\uff0c\u5982\u679c\u6211\u4eec\u68c0\u67e5\u6211\u4eec\u7684\u5458\u5de5\uff0c\u5b83\u7684\u5e74\u9f84\u5c06\u8bbe\u7f6e\u4e3a 0\uff08int \u7c7b\u578b\u7684\u9ed8\u8ba4\u503c\uff09\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1205.gif\" alt=\"Alt text\" \/><\/p>\n<p>Finally, let\u2019s return a value of 28 for the Age property:<br \/>\n\u6700\u540e\uff0c\u8ba9\u6211\u4eec\u4e3a Age \u5c5e\u6027\u8fd4\u56de\u503c 28\uff1a<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n&#x5B;\n    {\n        &quot;op&quot;:&quot;add&quot;,\n        &quot;path&quot;:&quot;\/age&quot;,\n        &quot;value&quot;:&quot;28&quot;\n    }\n]\n<\/pre>\n<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\"><a href=\"https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D\">https:\/\/localhost:5001\/api\/companies\/C9D4C053-49B6-410C-BC78-2D54A9991870\/employees\/80ABBCA8-664D<\/a><\/a><\/a>- 4B20-B5DE-024705497D4A<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1206.jpg\" alt=\"Alt text\" \/><\/p>\n<p>Let\u2019s check the employee now:<br \/>\n\u73b0\u5728\u8ba9\u6211\u4eec\u68c0\u67e5\u4e00\u4e0b\u5458\u5de5\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1207.gif\" alt=\"Alt text\" \/><\/p>\n<p>Excellent.<br \/>\n\u975e\u5e38\u597d\u3002<\/p>\n<p>Everything is working well.<br \/>\n\u4e00\u5207\u6b63\u5e38\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>12 WORKING WITH PATCH REQUESTS In the previous chapter, we worked with the PUT request to fully update our resource. But if we want to update our resource only partially, we should use PATCH. \u5728\u4e0a\u4e00\u7ae0\u4e2d\uff0c\u6211\u4eec\u4f7f\u7528 PUT \u8bf7\u6c42\u6765\u5b8c\u5168\u66f4\u65b0\u6211\u4eec\u7684\u8d44\u6e90\u3002\u4f46\u662f\uff0c\u5982\u679c\u6211\u4eec\u53ea\u60f3\u90e8\u5206\u66f4\u65b0\u6211\u4eec\u7684\u8d44\u6e90\uff0c\u6211\u4eec\u5e94\u8be5\u4f7f\u7528 PATCH\u3002 The partial update isn\u2019t the only difference between PATCH and PUT. The request body is different as [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[23],"class_list":["post-246","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-ultimate-asp-net-core-web-api"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=246"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/246\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}