{"id":234,"date":"2023-10-08T22:45:51","date_gmt":"2023-10-08T14:45:51","guid":{"rendered":"https:\/\/miie.net\/?p=234"},"modified":"2023-10-08T22:45:51","modified_gmt":"2023-10-08T14:45:51","slug":"ultimate-asp-net-core-web-api-chapter10-working-with-delete-requests","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=234","title":{"rendered":"Chapter10:WORKING WITH DELETE REQUESTS"},"content":{"rendered":"<h1>10 WORKING WITH DELETE REQUESTS<\/h1>\n<p>Let\u2019s start this section by deleting a child resource first. So, let\u2019s modify the IEmployeeRepository interface:<\/p>\n<\/p>\n<p>\u8ba9\u6211\u4eec\u5148\u5220\u9664\u5b50\u8d44\u6e90\uff0c\u4ece\u672c\u8282\u5f00\u59cb\u3002\u56e0\u6b64\uff0c\u8ba9\u6211\u4eec\u4fee\u6539 IEmployeeRepository \u63a5\u53e3\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic interface IEmployeeRepository\n{\n    IEnumerable&lt;Employee&gt; GetEmployees(Guid companyId, bool trackChanges);\n    Employee GetEmployee(Guid companyId, Guid id, bool trackChanges);\n\n    void CreateEmployeeForCompany(Guid companyId, Employee employee);\n\n    void DeleteEmployee(Employee employee);\n}\n<\/pre>\n<\/p>\n<p>The next step for us is to modify the EmployeeRepository class:<br \/>\n\u4e0b\u4e00\u6b65\u662f\u4fee\u6539 EmployeeRepository \u7c7b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void DeleteEmployee(Employee employee) { Delete(employee); }\n<\/pre>\n<\/p>\n<p>Finally, we can add a delete action to the controller class:<br \/>\n\u6700\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u5411\u63a7\u5236\u5668\u7c7b\u6dfb\u52a0\u4e00\u4e2a\u5220\u9664\u64cd\u4f5c\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;HttpDelete(&quot;{id}&quot;)]\npublic IActionResult DeleteEmployeeForCompany(Guid companyId, Guid id)\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 employeeForCompany = _repository.Employee.GetEmployee(companyId, id, trackChanges: false);\n    if (employeeForCompany == null)\n    {\n        _logger.LogInfo($&quot;Employee with id: {id} doesn&#039;t exist in the database.&quot;);\n        return NotFound();\n    }\n    _repository.Employee.DeleteEmployee(employeeForCompany);\n    _repository.Save(); return NoContent();\n}\n<\/pre>\n<\/p>\n<p>There is nothing new with this action. We collect the companyId from the root route and the employee\u2019s id from the passed argument. We have to check if the company exists. Then, we check for the employee entity.<br \/>\n\u6b64\u64cd\u4f5c\u6ca1\u6709\u4ec0\u4e48\u65b0\u9c9c\u4e8b\u3002\u6211\u4eec\u4ece\u6839\u8def\u7531\u6536\u96c6\u516c\u53f8 ID\uff0c\u4ece\u4f20\u9012\u7684\u53c2\u6570\u4e2d\u6536\u96c6\u5458\u5de5\u7684 ID\u3002\u6211\u4eec\u5fc5\u987b\u68c0\u67e5\u516c\u53f8\u662f\u5426\u5b58\u5728\u3002\u7136\u540e\uff0c\u6211\u4eec\u68c0\u67e5\u5458\u5de5\u5b9e\u4f53\u3002<\/p>\n<p>Finally, we delete our employee and return the NoContent() method, which returns the status code 204 No Content.<br \/>\n\u6700\u540e\uff0c\u6211\u4eec\u5220\u9664\u6211\u4eec\u7684\u5458\u5de5\u5e76\u8fd4\u56de NoContent\uff08\uff09 \u65b9\u6cd5\uff0c\u8be5\u65b9\u6cd5\u8fd4\u56de\u72b6\u6001\u4ee3\u7801 204 No Content\u3002<\/p>\n<p>Let\u2019s test this:<br \/>\n\u8ba9\u6211\u4eec\u6d4b\u8bd5\u4e00\u4e0b\uff1a<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1\"><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1\"><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1\">https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1<\/a><\/a><\/a><\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1001.jpg\" alt=\"Alt text\" \/><\/p>\n<p>Excellent. It works great.<br \/>\n\u975e\u5e38\u597d\u3002\u6548\u679c\u5f88\u597d\u3002<\/p>\n<p>You can try to get that employee from the database, but you will get 404 for sure:<br \/>\n\u60a8\u53ef\u4ee5\u5c1d\u8bd5\u4ece\u6570\u636e\u5e93\u4e2d\u83b7\u53d6\u8be5\u5458\u5de5\uff0c\u4f46\u60a8\u80af\u5b9a\u4f1a\u5f97\u5230 404\uff1a<\/p>\n<p><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1\"><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1\"><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1\">https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\/employees\/DE662003-ACC3-4F9F-9D82-0A74F64594C1<\/a><\/a><\/a><\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1002.gif\" alt=\"Alt text\" \/><\/p>\n<p>We can see that the DELETE request isn\u2019t safe because it deletes the resource, thus changing the resource representation. But if we try to send this delete request one or even more times, we would get the same 404 result because the resource doesn\u2019t exist anymore. That\u2019s what makes the DELETE request idempotent.<br \/>\n\u6211\u4eec\u53ef\u4ee5\u770b\u5230 DELETE \u8bf7\u6c42\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u5b83\u5220\u9664\u4e86\u8d44\u6e90\uff0c\u4ece\u800c\u6539\u53d8\u4e86\u8d44\u6e90\u8868\u793a\u5f62\u5f0f\u3002\u4f46\u662f\uff0c\u5982\u679c\u6211\u4eec\u5c1d\u8bd5\u53d1\u9001\u6b64\u5220\u9664\u8bf7\u6c42\u4e00\u6b21\u751a\u81f3\u591a\u6b21\uff0c\u6211\u4eec\u5c06\u5f97\u5230\u76f8\u540c\u7684 404 \u7ed3\u679c\uff0c\u56e0\u4e3a\u8d44\u6e90\u4e0d\u518d\u5b58\u5728\u3002\u8fd9\u5c31\u662f\u4f7f DELETE \u8bf7\u6c42\u5177\u6709\u5e42\u7b49\u6027\u7684\u539f\u56e0\u3002<\/p>\n<h2>10.1 Deleting a Parent Resource with its CHILDREN<\/h2>\n<p>With Entity Framework Core, this action is pretty simple. With the basic configuration, cascade deleting is enabled, which means deleting a parent resource will automatically delete all of its children. We can confirm that from the migration file:<br \/>\n\u4f7f\u7528\u5b9e\u4f53\u6846\u67b6\u6838\u5fc3\uff0c\u6b64\u64cd\u4f5c\u975e\u5e38\u7b80\u5355\u3002\u4f7f\u7528\u57fa\u672c\u914d\u7f6e\u65f6\uff0c\u5c06\u542f\u7528\u7ea7\u8054\u5220\u9664\uff0c\u8fd9\u610f\u5473\u7740\u5220\u9664\u7236\u8d44\u6e90\u5c06\u81ea\u52a8\u5220\u9664\u5176\u6240\u6709\u5b50\u8d44\u6e90\u3002\u6211\u4eec\u53ef\u4ee5\u4ece\u8fc1\u79fb\u6587\u4ef6\u4e2d\u786e\u8ba4\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1003.jpg\" alt=\"Alt text\" \/><\/p>\n<p>So, all we have to do is to create a logic for deleting the parent resource.<br \/>\n\u56e0\u6b64\uff0c\u6211\u4eec\u6240\u8981\u505a\u7684\u5c31\u662f\u521b\u5efa\u4e00\u4e2a\u7528\u4e8e\u5220\u9664\u7236\u8d44\u6e90\u7684\u903b\u8f91\u3002<\/p>\n<p>Well, let\u2019s do that following the same steps as in a previous example:<br \/>\n\u597d\u5427\uff0c\u8ba9\u6211\u4eec\u6309\u7167\u4e0e\u524d\u9762\u793a\u4f8b\u4e2d\u76f8\u540c\u7684\u6b65\u9aa4\u6267\u884c\u6b64\u64cd\u4f5c\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic interface ICompanyRepository\n{\n    IEnumerable&lt;Company&gt; GetAllCompanies(bool trackChanges);\n    Company GetCompany(Guid companyId, bool trackChanges);\n    void CreateCompany(Company company);\n\n    IEnumerable&lt;Company&gt; GetByIds(IEnumerable&lt;Guid&gt; ids, bool trackChanges);\n\n    void DeleteCompany(Company company);\n}\n<\/pre>\n<\/p>\n<p>Then let\u2019s modify the repository class:<br \/>\n\u7136\u540e\u8ba9\u6211\u4eec\u4fee\u6539\u5b58\u50a8\u5e93\u7c7b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void DeleteCompany(Company company) { Delete(company); }\n<\/pre>\n<\/p>\n<p>Finally, let\u2019s modify our controller:<br \/>\n\u6700\u540e\uff0c\u8ba9\u6211\u4eec\u4fee\u6539\u6211\u4eec\u7684\u63a7\u5236\u5668\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#x5B;HttpDelete(&quot;{id}&quot;)]\npublic IActionResult DeleteCompany(Guid id)\n{\n    var company = _repository.Company.GetCompany(id, trackChanges: false); \n    if (company == null)\n    {\n        _logger.LogInfo($&quot;Company with id: {id} doesn&#039;t exist in the database.&quot;); \n        return NotFound();\n    }\n    _repository.Company.DeleteCompany(company);\n    _repository.Save();\n    return NoContent();\n}\n<\/pre>\n<\/p>\n<p>And let\u2019s test our action:<br \/>\n\u8ba9\u6211\u4eec\u6d4b\u8bd5\u4e00\u4e0b\u6211\u4eec\u7684\u64cd\u4f5c\uff1a<br \/>\n<a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\"><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\"><a href=\"https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557\">https:\/\/localhost:5001\/api\/companies\/0AD5B971-FF51-414D-AF01-34187E407557<\/a><\/a><\/a><\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_1004.jpg\" alt=\"Alt text\" \/><\/p>\n<p>It works.<br \/>\n\u5b83\u6709\u6548\u3002<\/p>\n<p>You can check in your database that this company alongside its children doesn\u2019t exist anymore.<br \/>\n\u60a8\u53ef\u4ee5\u5728\u6570\u636e\u5e93\u4e2d\u68c0\u67e5\u8fd9\u5bb6\u516c\u53f8\u53ca\u5176\u5b50\u516c\u53f8\u662f\u5426\u4e0d\u518d\u5b58\u5728\u3002<\/p>\n<p>There we go. We have finished working with DELETE requests and we are ready to continue to the PUT requests.<br \/>\n\u6211\u4eec\u5f00\u59cb\u5427\u3002\u6211\u4eec\u5df2\u7ecf\u5b8c\u6210\u4e86\u5bf9 DELETE \u8bf7\u6c42\u7684\u5904\u7406\uff0c\u6211\u4eec\u5df2\u51c6\u5907\u597d\u7ee7\u7eed\u5904\u7406 PUT \u8bf7\u6c42\u3002<\/p>\n<p>For the PUT requests, we are going to inspect our console window for the SQL generated commands. If you can\u2019t see those, then just add this code in the <strong>appsettings.json<\/strong> file:<br \/>\n\u5bf9\u4e8e PUT \u8bf7\u6c42\uff0c\u6211\u4eec\u5c06\u68c0\u67e5\u63a7\u5236\u53f0\u7a97\u53e3\u4e2d\u662f\u5426\u6709 SQL \u751f\u6210\u7684\u547d\u4ee4\u3002\u5982\u679c\u60a8\u770b\u4e0d\u5230\u8fd9\u4e9b\uff0c\u5219\u53ea\u9700\u5728appsettings.json\u6587\u4ef6\u4e2d\u6dfb\u52a0\u6b64\u4ee3\u7801\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n  &quot;Logging&quot;: {\n    &quot;LogLevel&quot;: {\n      &quot;Default&quot;: &quot;Information&quot;,\n      &quot;Microsoft&quot;: &quot;Warning&quot;,\n      &quot;Microsoft.Hosting.Lifetime&quot;: &quot;Information&quot;,\n      &quot;Microsoft.EntityFrameworkCore&quot;: &quot;Information&quot;\n    }\n  },\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>10 WORKING WITH DELETE REQUESTS Let\u2019s start this section by deleting a child resource first. So, let\u2019s modify the IEmployeeRepository interface: \u8ba9\u6211\u4eec\u5148\u5220\u9664\u5b50\u8d44\u6e90\uff0c\u4ece\u672c\u8282\u5f00\u59cb\u3002\u56e0\u6b64\uff0c\u8ba9\u6211\u4eec\u4fee\u6539 IEmployeeRepository \u63a5\u53e3\uff1a public interface IEmployeeRepository { IEnumerable&lt;Employee&gt; GetEmployees(Guid companyId, bool trackChanges); Employee GetEmployee(Guid companyId, Guid id, bool trackChanges); void CreateEmployeeForCompany(Guid companyId, Employee employee); void DeleteEmployee(Employee employee); } The next step for us is [&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-234","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\/234","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=234"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}