【问题标题】:REST Patch in dotnet/meditr best practicesdotnet/meditr 最佳实践中的 REST 补丁
【发布时间】:2021-06-18 21:31:32
【问题描述】:

我使用 PUT/POST 来更新我正在使用的应用程序,到目前为止这一直很简单。现在我正在开发一个 API,它应该公开一种更新数据库中数据的方法,我最初的想法是我可以替换该行(或部分替换它)。由于具有不同数据知识的不同应用程序需要更新,我认为使用 PATCH 操作而不是 PUT 可能是个好主意。

我可以找到一些在控制器中实现更新的玩具示例,我对此并不感兴趣。

我使用与 jasontaylordev 的 Clean architecture 项目中相同的模式(CQRS w. Mediatr),所以我将在我的示例中使用它。

我有两个问题。

  1. 我不喜欢 JsonPatchDocument 对象应该到达我的处理程序,但我不知道如何避免这种情况。从控制器访问数据库不是一种选择。那么还有其他选择吗? (n.b. Automapper 或类似的动态映射库在我正在处理的项目中都不是一个选项)

  2. 如何从客户端应用程序(所有 dotnet 核心项目)构建 JsonPatch 对象。我认为如果我可以在具有两个属性TitleNote 以及Title="test"Note=null 的应用程序中拥有一个DTO,那么它应该替换标题并删除注释。我能以简单的方式映射到(奇怪的)补丁对象吗?

     [HttpPatch("{id}")]
     public async Task<ActionResult> Update(int id, UpdateTodoItemCommand command)
     {
      if (id != command.Id)
       {
      return BadRequest();
      }
    
     await Mediator.Send(command);
    
     return NoContent();
     }
    
     public class UpdateTodoItemCommand : IRequest
     {
       public int Id { get; set; }
    
       public JsonPatchDocument<TodoItemDto> Todo { get; set; }
     }
    
     public class TodoItemDto
     {
       public string Title { get; set; }
    
       public string Note { get; set; }
     }
    
    
     public class UpdateTodoItemCommandHandler : IRequestHandler<UpdateTodoItemCommand>
     {
       private readonly IApplicationDbContext _context;
    
       public UpdateTodoItemCommandHandler(IApplicationDbContext context)
       {
        _context = context;
       }
    
     public async Task<Unit> Handle(UpdateTodoItemCommand request, CancellationToken cancellationToken)
     {
         var entity = await _context.TodoItems.FindAsync(request.Id);
    
         if (entity == null)
         {
             throw new NotFoundException(nameof(TodoItem), request.Id);
         }
    
         var todoItemDto = new TodoItemDto();
         todoItemDto.Title = entity.Title;
         todoItemDto.Note = entity.Note: 
    
         todoItemDto.Todo.ApplyTo(request.Todo);
    
         entity.Title = todoItemDto.Title;
         entity.Note = todoItemDto.Note;
    
         await _context.SaveChangesAsync(cancellationToken);
    
         return Unit.Value;
     }
    }
    

【问题讨论】:

  • 通过 JsonPatch 对象是什么意思?您是指 ASP.NET Core 中的 JsonPatchDocument 吗?
  • 是的,我的意思是 JsonPatchDocument

标签: .net .net-core patch mediatr


【解决方案1】:

`JsonPatchDocument 是一个非常简单的对象,代表 JSON Patch RFC。它本质上是一组指令。如果您不想使用它,因为您不希望内置的 Microsoft 实现出现在您的处理程序中,那么您必须

  • 创建您自己的类(例如 UpdateCommand,它本身与补丁文档非常相似;接受“替换”、“删除”等指令。
  • 将补丁文档映射到此类的实例并通过 Mediatr 路由
  • 重新创建已从 asp.net 工具箱中提供的“修补机制”

要避免仅引用该参考,似乎需要做很多事情。如果您愿意,您也许可以创建一个保存文档的命令,但这并没有多大作用。

我创建的一个实现只接受 JsonPatchDocument 并将其传递给应用补丁的策略类(该策略类与 Mediatr 扮演相同的角色,因此实际上是同一件事。然后我针对资源调用 Apply() 方法.

【讨论】:

  • 我想我会在我的处理程序中使用 JsonPatchDocument。但是,首先将域实体中的字段传输到 DTO,然后将 JsonPatchDocument 中的操作应用到 DTO,最后将 DTO 映射到域对象,然后将其保存到数据库,这是标准做法吗?
  • 此外,我还在使用作为 mediatr 管道一部分的 Fluentvlidation。所以这是我不知道如何以优雅的方式解决的另一件事。
  • 我不知道这是否是标准做法。您的系统是记录系统还是参考系统?这会有所不同。
  • 可以从 API 访问的数据是“真相”,尽管在系统中找到的部分记录会在其他系统中复制(在另一个上下文中)以避免过于繁琐的服务无法独立工作.当获取最新信息以及添加和更新记录很重要时,该 API 将用于读取。
猜你喜欢
  • 2010-10-29
  • 1970-01-01
  • 2020-03-22
  • 2013-10-23
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 2020-05-29
相关资源
最近更新 更多