.NET 6开发TodoList应用之实现DELETE请求与HTTP请求幂等性

2022-04-16 11:47:07
目录
需求目标原理与思路实现验证总结

需求

先说明一下关于原本想要去更新的PATCH请求的文章,从目前试验的情况来看,如果是按照.NET 6的项目结构(即只使用一个Program.cs完成程序初始化),那微软官方给出的文档目前还没有对应地更新,按照之前的方式进行jsonPatch的配置是不行的,目前已经有人在github微软的官方文档Repo下提了ISSUE: .NET 6: JsonPatch in ASP.NET Core web API。并且因为PATCH的使用频率并不高,所以我暂时跳过那篇,先把进度继续往后走,看微软什么时候把这个issue解决一下我再看情况把PATCH那一节补上。

本文我们来看最后一个常用HTTP请求类型:DELETE。

目标

实现并验证应用正确处理DELETE请求。并对HTTP请求的幂等性做简单的介绍。

原理与思路

经过关于Create、Update、Get的实现,对于Delete的实现我们的思路是很清晰的。我们需要创建Delete的Command及其Handler,然后在Controller中通过Mediatr发送请求即可。

实现

在Application/TodoList下新建DeleteTodoList文件夹,并新建DeleteTodoListCommand:

DeleteTodoListCommand.cs

using MediatR;using TodoList.Application.Common.Exceptions;using TodoList.Application.Common.Interfaces;namespace TodoList.ApbNIdeejIplication.TodoLists.Commands.DeleteTodoList;public class DeleteTodoListCommand : IRequest{    public Guid Id { get; set; }}public class DeleteTodoListCommandHandler : IRequestHandler<DeleteTodoListCommand>{    private readonly IRepository<Domain.Entities.TodoList> _repository;    public De易采站长站leteTodoListCommandHandler(IRepository<Domain.Entities.TodoList> repository)    {        _repository = repository;    }    public async Task<Unit> Handle(DeleteTodoListCommand request, CancellationToken cancellationToken)    {        var entity = await _repository.GetAsync(request.Id);        if (entity == null)        {            throw new NotFoundException(nameof(TodoList), request.Id);        }        await _repository.DeleteAsync(entity,cancellationToken);        // 对于Delete操作,演示中并不返回任何实际的对象,可以结合实际需要返回特定的对象。Unit对象在MediatR中表示Void        return Unit.Value;    }}

在Controller中添加Delete的接口处理:

TodoListController.cs

// 省略其他...[HttpDelete("{id:guid}")]public async Task<ApiResponse<object>> Delete(Guid id){    return ApiResponse<object>.Success(await _mediator.Send(new DeleteTodoListCommand { Id = id }));}

这里可能值得强调的是关于EntityFrameworkCore中对于关联实体DELETE操作的处理方式:

打开Infrastructure/MigrationbNIdeejIs文件夹,我们可以在迁移领域实体的那次Migration生成的.Designer.cs文件中发现这样一段配置:

// 省略其他...modelBuilder.Entity("TodoList.Domain.Entities.TodoItem", b =>    {        b.HasOne("TodoList.Domain.Entities.TodoList", "List")            .WithMany("Items")            .HasForeignKey("ListId")            .OnDelete(DeleteBehavior.Cascade)            .IsRequired();        b.Navigation("List");    });

可以看到在OnDelete中配置的是DeleteBehavior.Cascade行为模式,关于DeleteBehavior,可以参考Referential Constraint Action Options。实际上总共有七种可以设置的行为模式:

DeleteBehavior.Cascade DeleteBehavior.NoAction DeleteBehavior.Restrict DeleteBehavior.SetNull DeleteBehavior.ClientCascade DeleteBehavior.ClientNoAction DeleteBehavior.ClientSetNull

关于这七种DeleteBehavior,可以参考这篇博文:Entity Framework Core 关联删除,博主在其中进行了比较详细的实验和总结。

可以根据实际需要去显式地配置DeleteBehavior。另外,习惯观察生成的Migrations文件,也是学习EFCore一些惯例或者说默认配置的很好的方法。

验证

启动Api项目,发送DELETE请求:

请求

.NET6开发TodoList应用之实现DELETE请求与HTTP请求幂等性

响应

.NET6开发TodoList应用之实现DELETE请求与HTTP请求幂等性

并且从数据库里我们以可以发现,这条TodoList下包含的TodoItem也被一同删除了。

总结