You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastEndpoints启用数据注解验证及统一错误响应格式求助

解决方案

1. 启用数据注解验证替代Fluent Validation

FastEndpoints默认使用Fluent Validation,要切换到数据注解验证,只需在服务配置中替换验证器工厂:

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddFastEndpoints(config =>
{
    // 替换为数据注解验证器工厂
    config.Validation.ValidatorFactoryType = typeof(DataAnnotationsValidatorFactory);
});

var app = builder.Build();

app.UseFastEndpoints();
app.Run();

之后在跨项目共享的请求类上直接使用.NET内置的数据注解即可:

// 跨项目共享的请求类
public class CreateUserRequest
{
    [Required(ErrorMessage = "用户名不能为空")]
    [StringLength(20, ErrorMessage = "用户名长度不能超过20个字符")]
    public string Username { get; set; }

    [EmailAddress(ErrorMessage = "邮箱格式不正确")]
    public string Email { get; set; }

    [Range(18, 100, ErrorMessage = "年龄必须在18到100之间")]
    public int Age { get; set; }
}

2. 统一返回单一字符串数组的验证错误

要消除嵌套的属性级错误结构,返回扁平的错误消息数组,需要自定义错误响应处理器:

步骤1:实现自定义错误响应处理器

public class FlatErrorResponseProcessor : IErrorResponseProcessor
{
    public ValueTask<object> ProcessAsync(ValidationFailure[] failures, HttpContext ctx, IReadOnlyCollection<ValidationFailure> state, CancellationToken ct)
    {
        // 提取所有错误消息,不管是属性级还是通用错误
        var errorMessages = failures.Select(f => f.ErrorMessage).ToArray();
        return ValueTask.FromResult<object>(new { Errors = errorMessages });
    }
}

步骤2:注册自定义处理器

在FastEndpoints配置中指定这个处理器:

// Program.cs
builder.Services.AddFastEndpoints(config =>
{
    config.Validation.ValidatorFactoryType = typeof(DataAnnotationsValidatorFactory);
    // 注册自定义错误响应处理器
    config.Validation.ErrorResponseProcessor = new FlatErrorResponseProcessor();
});

步骤3:手动添加通用错误(可选)

如果需要在业务逻辑中添加非属性级的通用错误,直接在端点中使用AddError方法即可,这些错误会自动加入到扁平数组中:

public class CreateUserEndpoint : Endpoint<CreateUserRequest>
{
    public override void Configure()
    {
        Post("/api/users");
        AllowAnonymous();
    }

    public override async Task HandleAsync(CreateUserRequest req, CancellationToken ct)
    {
        // 模拟业务逻辑校验错误
        if (await UserExistsAsync(req.Username))
        {
            AddError("该用户名已被注册");
            await SendErrorsAsync(ct);
            return;
        }

        // 正常业务逻辑
        await SendOkAsync("用户创建成功", ct);
    }

    private Task<bool> UserExistsAsync(string username)
    {
        // 模拟数据库查询
        return Task.FromResult(username == "admin");
    }
}

最终响应示例

当存在验证错误时,返回的响应结构如下:

{
  "Errors": [
    "用户名不能为空",
    "邮箱格式不正确",
    "该用户名已被注册"
  ]
}

内容的提问来源于stack exchange,提问作者DrXSsive

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 05:52:34