FastEndpoints是一款友好的,开源的,免费的可替换Minimal APIs和MVC的第三方库,是基于REPR(Request-Endpoint-Response)设计模式设计的API,方便且易于维护没有模板。性能方面几乎媲美Minimal APIs,低内存使用,每秒请求处理要比MVC快35K。FastEndpoints库提供了如下功能:认证和授权,模型绑定,验证,依赖注入,实体映射,文件处理,响应缓存,限流,预处理器,事件总线,命令总线,任务队列,远程调用等。
下面是官方给出的测评:
TechEmpower Benchmark (Preliminary)

我们通过一个例子来了解一下该库
1. 创建项目并安装FastEndpoints包
添加FastEndpoints包:
2. 添加服务以及中间件
使用下面代码替换Program.cs
// 堆代码 duidaima.com
using FastEndpoints;
var bld = WebApplication.CreateBuilder();
bld.Services.AddFastEndpoints();
var app = bld.Build();
app.UseFastEndpoints();
app.Run();
3. 添加Request DTO
创建一个MyRequest类:
public class MyRequest
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
4. 添加Response DTO
创建一个MyResponse类
public class MyResponse
{
public string FullName { get; set; }
public bool IsOver18 { get; set; }
}
5. 添加一个终结点类
添加一个终结点类
using FastEndpoint.Libaray.Models;
using FastEndpoints;
public class MyEndpoint : Endpoint<MyRequest, MyResponse>
{
public override void Configure()
{
Post("/api/user/create");
AllowAnonymous();
}
public override async Task HandleAsync(MyRequest req, CancellationToken ct)
{
await SendAsync(new()
{
FullName = req.FirstName + " " + req.LastName,
IsOver18 = req.Age > 18
});
}
}
运行应用程序向/api/user/create发送一个POST请求

响应

你只需要在Configure()方法中配置终结点如何监听从客户端进入的请求。例如:Get(), Post(), AllowAnonymous() 等,然后重写HandleAsync()方法指定你处理逻辑。
在这个例子中,请求DTO自动从HTTP请求的body中获取数据并且传递处理。处理之后,调用SendAsync()方法将新的DTO实例发送到客户端。
6. 终结点类型
你可以继承4种不同类型的endpoint
Endpoint<TRequest>如果只有一个请求DTO,你可以继承这个类型。
Endpoint<TRequest,TResponse> - 如果您同时具有请求和响应DTO,请继承此类型。
EndpointWithoutRequest - 如果没有请求或响应DTO,继承此类型。
EndpointWithoutRequest<TResponse> 如果没有请求DTO但存在响应DTO,请继承此类型。
你也可以使用自定义EmptyRequest和EmptyResponse定义一个终结点
public class MyEndpoint : Endpoint<EmptyRequest,EmptyResponse> { }
7. 发送响应
FastEndpoints提供了多种请求响应方法。您还可以简单地填充端点的 Response 属性,并自动在响应主体中序列化 Response 属性的值,从而获得一个 200 OK 的响应。例如:
public class MyEndpoint : EndpointWithoutRequest<MyResponse>
{
public override void Configure()
{
Get("/api/person");
AllowAnonymous();
}
public override async Task HandleAsync(CancellationToken ct)
{
var person = await dbContext.GetFirstPersonAsync();
Response.FullName = person.FullName;
Response.Age = person.Age;
}
}
也可以使用另外一种方式:
public override Task HandleAsync(CancellationToken ct)
{
Response = new()
{
FullName = "john doe",
Age = 124
};
return Task.CompletedTask;
}
8. 返回多个类型
可以调用TypedResult类的静态方法来返回不同的结果类型。根据需要的结果类型,通过调用TypedResults类的静态方法实例化结果对象。
FastEndpoint也支持响应DTO类型设置为泛型联合多个参数,并覆盖ExecuteAsync(…)处理程序方法,而不是常用的HandleAsync(…)方法。
public class MyEndpoint : Endpoint<MyRequest,
Results<Ok<MyResponse>,
NotFound,
ProblemDetails>>
{
public override void Configure() { ... }
public override async Task<Results<Ok<MyResponse>, NotFound, ProblemDetails>> ExecuteAsync(
MyRequest req, CancellationToken ct)
{
await Task.CompletedTask; //simulate async work
if (req.Id == 0) //condition for a not found response
{
return TypedResults.NotFound();
}
if (req.Id == 1) //condition for a problem details response
{
AddError(r => r.Id, "value has to be greater than 1");
return new FastEndpoints.ProblemDetails(ValidationFailures);
}
// 堆代码 duidaima.com
// 200 ok response with a DTO
return TypedResults.Ok(new MyResponse
{
RequestedId = req.Id
});
}
}
如果只有一个输出类型,设置终结点泛型参数TResponse为想要IResult类型
public class MyEndpoint : EndpointWithoutRequest<NotFound>
{
public override void Configure() { ... }
public override async Task<NotFound> ExecuteAsync(CancellationToken ct)
{
await Task.CompletedTask;
return TypedResults.NotFound();
}
}
如果你想使用HandleAsync()发送TypedResults,你可以使用下面方式:
public class MyEndpoint : Endpoint<MyRequest, Results<Ok<MyResponse>, NotFound>>
{
public override void Configure() { ... }
public override async Task HandleAsync(MyRequest r, CancellationToken c)
{
if (true)
await SendResultAsync(TypedResults.Ok<MyResponse>(new(){ ... }));
else
await SendResultAsync(TypedResults.NotFound());
}
}
9. 使用Attributes进行配置
同样的,FastEndpoints也提供了attributes方式来配置终结点:
[Http{VERB}("/route")] - 指定请求动词和路由
[AllowAnonymous] - 允许匿名访问
[Authorize(...)] - 使用角色和策略指定授权
[PreProcessor<TProcessor>] - 在管道中添加一个前置处理器
[PostProcessor<TProcessor>] - 在管道中添加一个post处理器
[HttpPost("/my-endpoint")]
[Authorize(Roles = "Admin,Manager")]
[PreProcessor<MyProcessor>]
public class MyEndpoint : Endpoint<MyRequest, MyResponse>
{
...
}
你在任何终结点上设置的attribute都会自动添加到终结点元数据集合,这种方式和在Configure()使用如下方法时等同的:
Options(b => b.WithMetadata(new MyCustomAttribute()));
10. Cancellation Token
终结点的HandleAsync方法提供了一个CancellationToken参数,你可以在自己的业务方法中使用这个参数。CancellationToken参数对于终结点Send*Async方法可选,你不需要像下面这样手动提供一个CancellationToken参数:
await SendAsync(response, cancellation: ct);
因为默认会提供一下相同的CancellationToken给SendAsync方法
Demo的Github地址:https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/Third-Party.Library/FastEndpoint.Library/FastEndpoint.Library