优雅的.net REST API之FastEndpoints

FastEndpoints 是基于 ASP.NET Core 的轻量级、高性能 Web API 开发框架,采用 REPR (请求-端点-响应)设计模式。

本人用FastEndpoints做了一个REST API很优雅的Case

一、以下是http测试

复制代码
@HostAddress = http://localhost:5167
### 获取列表
GET {{HostAddress}}/users?Page=1&Size=10

### 添加
PUT {{HostAddress}}/users
Content-Type:application/json

{
  "Name" : "Jxj"
}

### 获取单个
GET {{HostAddress}}/users/1

### 修改
PATCH {{HostAddress}}/users/1
Content-Type:application/json

{
  "Name" : "Jxj2"
}

### 删除
DELETE {{HostAddress}}/users/1

地址规则非常简单清晰,只有两种地址却能支持添、删、改、查四种操作

  1. 添加使用/users

使用PUT请求,含义是向一个集合添加资源

  1. 删除使用/users/{Id}(Id是标识)

使用DELETE请求,表示从集合移除该标识的资源

  1. 修改也使用/users/{Id}}(Id是标识)

使用PATCH请求,表示该标识资源的哪些字段被修改了(这与Elasticsearch的一样)

  1. 查询GET请求

4.1 查询单条使用/users/{Id}}(Id是标识)

4.2 查询多条使用/users

二、项目结构也是非常简单清晰

注:实际项目的模型和仓储应该是单独项目,这里简单示意就放一起了

本人非常喜欢这样的项目结构,每个API方法一个文件夹

而且每个文件夹下的文件名非常有意思,都是Endpoint、Mapper和Models,对于本人这种纠结命名规则的反而是一种解脱

应用层业务逻辑复杂的可以再增加一个Data.cs文件

这种文件结构FastEndpoints是有提供模板生成的,当然手动写也不复杂

三、Mapper的优雅实现

定义接口IPocoConverter实现任意两种类型的转化,直接用IOC注入就好了

以下是Create的Mapper的实现

复制代码
[RegisterService<Mapper>(LifeTime.Singleton)]
public sealed class Mapper(
    UserRepository repository, 
    IPocoConverter<Request, User> requestConverter, 
    IPocoConverter<User, Response> responseConverter)
    : Mapper<Request, Response, User>
{
    #region 配置
    private readonly UserRepository _repository = repository;
    private readonly IPocoConverter<Request, User> _requestConverter = requestConverter;
    private readonly IPocoConverter<User, Response> _responseConverter = responseConverter;
    #endregion
    public override User ToEntity(Request r)
    {
        User entity = _requestConverter.Convert(r);
        return Save(entity);
    }
    public override Response FromEntity(User e)
        => _responseConverter.Convert(e);
    #region Data
    User Save(User entity)
        => _repository.Add(entity);
    #endregion
}

这里有一个微软IOC不得不说的槽点,IServiceCollection支持泛型类的注册,却不支持泛型方法的注册

好在本人找到了博客园一个大佬(@coredx)的开源项目(https://www.cnblogs.com/coredx/p/18138360)

封装一个简单IOC注入泛型转化的方法如下:

复制代码
services.UseConverter(PocoEmit.Mapper.Global);

还需要显示调用@coredx的以下方法

复制代码
builder.Host.UseServiceProviderFactory(new TypedImplementationFactoryServiceProviderFactory());

注: 以上调用本人是翻开大佬源码才摸索出来的,按大佬的文档尝试了很多次都失败了,大佬的文档估计有些时间没更新了...

四、优雅的修改

本次修改还是使用的本人上篇文章(https://www.cnblogs.com/xiangji/p/18979384)提到的MyDelta,微软OData的Delta的变体

复制代码
public sealed class Endpoint(UserModifyDTOValidator validationRules) : Endpoint<Request, Response, Mapper>
{
    // ...
    public override async Task HandleAsync(Request req, CancellationToken c)
    {
        MyDelta<UserModifyDTO> dto = req.User;
        dto.Patch(dto.Instance);
        var result = validationRules.Validate(dto);
        if(!result.IsValid)
        {
            ThrowError(result.Errors[0]);
        }
        User? entity = Map.ToEntity(req);
        if (entity is null)
        {
            ThrowError($"Id = {req.Id} 的User不存在");
        }
        var res = Map.FromEntity(entity);
        await Send.OkAsync(res, c);
    }
}
复制代码
[RegisterService<Mapper>(LifeTime.Singleton)]
public sealed class Mapper(
    UserRepository repository,
    IMyDeltaFactory deltaFactory,
    IPocoConverter<User, Response> responseConverter)
    : Mapper<Request, Response, User?>
{
    // ...
    public override User? ToEntity(Request r)
    {
        var user0 = GetById(r.Id);
        if (user0 == null)
            return null;
        var delta = deltaFactory.Create(user0, r.User.Data);
        return Modify(delta);
    }
}

获取并验证DTO的MyDelta(增量),再转化为模型实体的增量,调用仓储处理

以下项目代码GitHub地址: https://github.com/donetsoftwork/MyEmit/tree/main/IntegrationTests/TestApi

gitee同步更新: https://gitee.com/donetsoftwork/MyEmit/tree/main/IntegrationTests/TestApi

如果大家喜欢请动动您发财的小手手帮忙点一下Star。

相关推荐
xiangji18 天前
PATCH请求REST API之MyDeltas.net
patch
小七de尾巴3 个月前
利用pnpm patch给第三方库打补丁
vue·pnpm·patch·补丁
EleganceJiaBao4 个月前
【嵌入式】嵌入式系统中的 SemVer 版本控制方案
c语言·stm32·嵌入式·patch·semver·major·minor
乐闻x9 个月前
如何使用 pnpm 进行打补丁patch操作?推荐两个方法
前端·javascript·pnpm·patch
___波子 Pro Max.1 年前
下载github patch到本地
git·patch
YasinLeeX1 年前
如何向linux社区提交一个新的驱动或patch
linux·ubuntu·驱动·patch·upstream·linux社区·review
dingdingfish1 年前
升级Oracle 单实例数据库19.3到19.22
oracle·database·patch·upgrade·19c
husterlichf2 年前
JSON Merge Patch && JSON PATH
http·json·merge·patch
woloqun2 年前
Spark低版本适配Celeborn
spark·编译·patch·celeborn·动态资源