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

.NET Core 5 Web API 400 Bad Request 处理更优实现模式咨询

.NET Core 5 Web API 400请求校验优化方案

方案1:使用内置数据注解+自动模型验证(无第三方依赖,无需修改模型继承结构)

ASP.NET Core Web API 自带模型校验能力,仅需给模型属性添加对应校验特性即可,无需调整现有模型的继承关系,对API调用方完全无感知,不会造成破坏性变更。

  1. 给模型属性添加校验特性
public class Customer
{
    [Required(ErrorMessage = "First name is required")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Last name is required")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Email address is required")]
    public string EmailAddress { get; set; }

    [Required(ErrorMessage = "At least one role is required")]
    [MinLength(1, ErrorMessage = "At least one role is required")]
    public List<string> Roles { get; set; }

    // 其他Customer专属属性
}

Employee模型同理,直接给对应需要校验的属性添加相同的[Required]等特性即可,不需要和Customer做任何继承关联。
2. 开启自动校验
确认控制器类上添加了[ApiController]特性,.NET Core 3.0+版本默认会对加了该特性的控制器自动执行模型校验,校验失败直接返回400响应,不需要在Action中写任何判断逻辑。
如果需要统一自定义400响应格式,可在Startup.cs的ConfigureServices方法中添加如下配置:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.InvalidModelStateResponseFactory = context =>
    {
        // 提取所有校验错误信息
        var errorList = context.ModelState
            .Where(m => m.Value.Errors.Any())
            .SelectMany(m => m.Value.Errors.Select(e => e.ErrorMessage))
            .ToList();
        // 返回自定义格式的400响应
        return new BadRequestObjectResult(new
        {
            Code = 400,
            Msg = "参数校验失败",
            Errors = errorList
        });
    };
});
  1. 简化后的Action代码
    所有的参数校验if语句都可以直接删除:
[HttpPost("register-customer")]
[Produces("application/json")]
[MapToApiVersion("1")]
public async Task<ActionResult<IRegistrationStatus>> RegisterCustomer([FromBody] Customer customer)
{
    try
    {
        // 到此处已经自动完成所有必填项校验,直接调用业务逻辑即可
        var registrationStatus = await _registerService.Register(customer);
        return Ok(registrationStatus);
    }
    catch (Exception ex)
    {
        return StatusCode(500, ex.ToString());
    }
}

如果需要实现更复杂的跨字段关联校验,可以让模型实现IValidatableObject接口,在Validate方法中编写自定义校验逻辑,自动校验流程也会触发该方法的执行。

方案2:使用FluentValidation实现更高复用性的校验逻辑

如果公共校验规则较多,想要避免重复编写相同的校验特性,可以使用FluentValidation库实现校验逻辑和模型的完全解耦,同样不需要修改现有模型的任何结构。

  1. 安装Nuget包
Install-Package FluentValidation.AspNetCore
  1. 注册服务
    在Startup.cs的ConfigureServices方法中添加:
services.AddFluentValidationAutoValidation();
// 扫描当前程序集中所有校验器自动注册
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
  1. 封装公共校验逻辑
// 公共校验基类,复用所有人名、邮箱等通用校验规则
public abstract class PersonValidator<T> : AbstractValidator<T> where T : class
{
    protected PersonValidator()
    {
        RuleFor("FirstName").NotEmpty().WithMessage("First name is required")
            .MaximumLength(50).WithMessage("First name不能超过50个字符");
        RuleFor("LastName").NotEmpty().WithMessage("Last name is required");
        RuleFor("EmailAddress").NotEmpty().EmailAddress().WithMessage("邮箱格式不正确");
    }
}
  1. 编写各自模型的校验器
// Customer专属校验器
public class CustomerValidator : PersonValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor(x => x.Roles).NotEmpty().WithMessage("At least one role is required");
        // 其他Customer专属校验规则
    }
}

// Employee专属校验器
public class EmployeeValidator : PersonValidator<Employee>
{
    public EmployeeValidator()
    {
        RuleFor(x => x.EmployeeNo).NotEmpty().WithMessage("工号不能为空");
        // 其他Employee专属校验规则
    }
}

所有校验逻辑完全独立于模型之外,现有模型不需要做任何修改,不会对API契约产生任何影响,公共校验规则仅需编写一次即可复用给所有符合条件的模型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:54:04