dotnet/medictr最佳实践中的REST补丁



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

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

我使用了与jasontaylordev的Clean架构项目中相同的模式(CQRS w.Mediator(,所以我将在我的示例中使用它。

我有两个问题。

  1. 我不喜欢JsonPatchDocument对象应该到达我的Handlers,但我不知道如何避免这种情况。不能从控制器访问数据库。那么还有其他选择吗?(注意:在我正在进行的项目中,Automapper或类似的动态映射库都不是选项(

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

    [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;
    }
    }
    

我遇到了同样的问题,我想出了一个适合我的解决方案。

在UpdateTodoItemCommandHandler类的Handle方法中,您将再创建一个JsonPatchDocument,但类型为TodoItem(而不是Dto(。然后将操作和ContractResolver转移到新的JsonPatchDocument对象,您可以对其进行修补并将其保存到数据库中。类似这样的东西:

var entity = await _context.TodoItems.FindAsync(request.Id);
if (entity == null)
{
throw new NotFoundException(nameof(TodoItem), request.Id);
}    
var todoItemPatch = new JsonPatchDocument<TodoItem>();
foreach (var opr in request.Todo.Operations)
{
todoItemPatch.Operations.Add(new Operation<TodoItem> 
{ 
op = opr.op, 
path = opr.path, 
value = opr.value 
});
}
todoItemPatch.ContractResolver = 
request.Todo.ContractResolver;
todoItemPatch.ApplyTo(entity);
await _context.SaveChangesAsync(cancellationToken);
JsonPatchDocument是一个非常简单的对象,表示JSON补丁RFC。它本质上是一套指令。如果你不想使用它,因为你不想让内置的Microsoft实现出现在你的处理程序中,那么你就必须使用
  • 创建自己的类(例如UpdateCommand,它本身与补丁文档非常相似;使用"replace"、"delete"等指令
  • 将修补程序文档映射到此类的实例,并通过Mediator进行路由
  • 重新创建asp.net工具箱中已经提供的"修补机制">

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

我创建的一个实现只需要获取JsonPatchDocument并将其传递给一个应用补丁的策略类(该策略类与Mediator扮演着相同的角色,因此实际上是相同的东西。然后我对该资源调用了Apply((方法。

相关内容

  • 没有找到相关文章

最新更新