就像 GET 404 响应一样,表示该资源不可用于更新,但这可能在稍后发生改变。另外,ASP.NET 提供现成的模型绑定验证。接下来,尝试一下使用错误的数据更新现有资源。
下面的 JSON 是您可能看到的 Bad Request 的响应:
{ "errors": { "Price": ["The price field is required."] }, "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "|c445a409-43564e0626f9af50." }PATCH 是所有动词中最复杂的,因为它通过 JSON Patch 文档仅更新资源的一部分。
庆幸的是 .NET Core 提供了一个 NuGet 包:
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson然后,在 ConfigureServices 中启用它:
services.AddControllers().AddNewtonsoftJson();下面是 PATCH Endpoint,记得添加 using Microsoft.AspNetCore.JsonPatch:
[HttpPatch] [Route("{productNumber}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult<Product> PatchProduct([FromRoute] string productNumber, [FromBody] JsonPatchDocument<Product> patch) { try { var productDb = _context.Products .FirstOrDefault(p => p.ProductNumber.Equals(productNumber, StringComparison.InvariantCultureIgnoreCase)); if (productDb == null) return NotFound(); patch.ApplyTo(productDb, ModelState); if (!ModelState.IsValid || !TryValidateModel(productDb)) return ValidationProblem(ModelState); _context.SaveChanges(); return Ok(productDb); } catch (Exception e) { _logger.LogWarning(e, "Unable to PATCH product."); return ValidationProblem(e.Message); } }我希望您看到一种含有不同状态码响应类型的模式开始浮现。200 OK 表示成功,400 Bad Request 表示用户错误。当 patch 被应用后,将会在 ModelState 中追加所有的验证错误。仔细看一下进行模型绑定的 JsonPatchDocument 和 应用更改的 ApplyTo。这就是将 JSON Patch 文档应用到数据库中现有产品的方式。像所有其它 Endpoints 一样,异常会被记录并包含在响应中。与其它动词一样,404 (Not Found) 响应表示相同的情形。响应状态码的一致性有助于客户端处理所有可能的场景。
一个 JSON patch 请求的 body 大概如下所示:
[{ "op": "replace", "path": "price", "value": 13.67 }]模型绑定验证规则依然适用于 patch 操作,以保持数据的完整性。请注意,patch 操作被包装在一个数组中,因此它支持任意的操作列表。
下图是 curl 中请求 PATCH 的结果:
最后一站,DELETE 方法:
[HttpDelete] [Route("{productNumber}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult<Product> DeleteProduct([FromRoute] string productNumber) { var productDb = _context.Products .FirstOrDefault(p => p.ProductNumber.Equals(productNumber, StringComparison.InvariantCultureIgnoreCase)); if (productDb == null) return NotFound(); _context.Products.Remove(productDb); _context.SaveChanges(); return NoContent(); }它的状态码响应是 No Content:
HTTP/1.1 204 No Content Date: Tue, 14 Jul 2020 22:59:20 GMT Server: Kestrel api-supported-versions: 1.0此状态向客户端发出信号,表示资源不再可用,因为响应主体为空。如果需要异步后台进程来清理数据,则响应也可以为 204 (Accepted)。在实际系统中,有时最好使用软删除,以允许在审核期间进行回滚。删除数据时,请确保遵守 GPDR 或适用于该数据的任一策略。
总结.NET Core 在您的工具袋中添加许多有用的特性,从而让使用 REST API 变得更加轻松,将诸如文档、验证、日志记录和 PATCH 请求等复杂的用例变得更易于实现。
作者 : Camilo Reyes
译者 : 技术译民
出品 : 技术译站
链接 : 英文原文
https://www.red-gate.com/simple-talk/dotnet/c-programming/build-a-rest-api-in-net-core/ Build a REST API in .NET Core
https://dotnet.microsoft.com/download/dotnet-core Download .NET Core
https://github.com/beautifulcoder/BuildRestApiNetCore 示例代码
https://rapidapi.com/blog/api-glossary/endpoint/ API Endpoints
https://semver.org/ Semantic Versioning
https://tools.ietf.org/html/rfc7807 RFC 7807 规范
https://tools.ietf.org/html/rfc6902 JSON Patch 文档