使用Fluent Validation处理GET请求:带请求体是否违规?如何验证查询参数?
关于GET请求使用Fluent Validator的问题解答
1. GET请求是否需要携带JSON请求体?这属于不良实践吗?
- GET请求完全没必要带JSON请求体,而且这是典型的不良实践。HTTP规范虽然没彻底禁止,但几乎所有主流的HTTP客户端、服务器和代理对GET请求的请求体支持都不一致,很容易出现请求丢失、解析失败或者跨环境兼容性问题。
- 按照HTTP语义和RESTful设计惯例,GET请求的参数就该通过URL的查询字符串传递,这样请求可以被缓存、添加书签,也符合开发者的普遍认知。
2. 用Fluent Validator验证GET请求的查询参数
要验证start、end等查询参数,最稳妥的做法是先把这些参数封装成一个DTO(数据传输对象),再用Fluent Validator对这个DTO定义验证规则。具体步骤如下:
步骤1:创建查询参数DTO
把所有查询参数封装到一个类中,方便统一验证:
public class SecuredTaxBillPreviewQuery { public int Start { get; set; } public int End { get; set; } public string Skip { get; set; } public int PageNumber { get; set; } public int PageSize { get; set; } }
步骤2:编写Fluent Validator验证规则
针对上述DTO创建验证器,定义start、end等参数的校验逻辑:
public class SecuredTaxBillPreviewQueryValidator : AbstractValidator<SecuredTaxBillPreviewQuery> { public SecuredTaxBillPreviewQueryValidator() { // 验证起始年份:限定合理范围,且不晚于结束年份 RuleFor(x => x.Start) .InclusiveBetween(2000, DateTime.Now.Year) .WithMessage("起始年份必须在2000到当前年份之间"); RuleFor(x => x.End) .InclusiveBetween(2000, DateTime.Now.Year) .WithMessage("结束年份必须在2000到当前年份之间") .GreaterThanOrEqualTo(x => x.Start) .WithMessage("结束年份不能早于起始年份"); // 分页参数基础校验 RuleFor(x => x.PageNumber) .GreaterThan(0) .WithMessage("页码必须大于0"); RuleFor(x => x.PageSize) .InclusiveBetween(1, 100) .WithMessage("每页条数必须在1到100之间"); } }
步骤3:在Controller中应用验证
修改Action,用DTO接收查询参数,并执行验证逻辑:
[HttpGet("preview/secured", Name = nameof(GetPreviewSecuredTaxBillData))] public IActionResult GetPreviewSecuredTaxBillData([FromQuery] SecuredTaxBillPreviewQuery query, IValidator<SecuredTaxBillPreviewQuery> validator) { // 执行参数验证 var validationResult = validator.Validate(query); if (!validationResult.IsValid) { // 返回验证错误列表 return BadRequest(validationResult.Errors); } var taxBills = securedTaxBillService.GetSecuredTaxBills(query.PageNumber, query.PageSize); return Ok(taxBills); }
可选:全局自动验证(ASP.NET Core)
如果不想在每个Action中手动写验证逻辑,可以注册Fluent Validation的全局过滤器,实现自动验证:
在Program.cs中添加以下配置:
builder.Services.AddFluentValidationAutoValidation(); builder.Services.AddFluentValidationClientsideAdapters(); // 注册自定义验证器 builder.Services.AddScoped<IValidator<SecuredTaxBillPreviewQuery>, SecuredTaxBillPreviewQueryValidator>();
之后Action可以简化为:
[HttpGet("preview/secured", Name = nameof(GetPreviewSecuredTaxBillData))] public IActionResult GetPreviewSecuredTaxBillData([FromQuery] SecuredTaxBillPreviewQuery query) { // 验证会自动执行,失败时直接返回400错误 var taxBills = securedTaxBillService.GetSecuredTaxBills(query.PageNumber, query.PageSize); return Ok(taxBills); }
内容的提问来源于stack exchange,提问作者Hoang Minh
相关产品推荐
相关产品推荐

