C# .NET API如何校验URL查询参数为绑定模型的合法属性
查询参数非法自动返回400的实现方案
.NET 7 及以上版本(原生支持)
.NET 7 开始框架内置了未映射查询参数的自动校验能力,属于开箱即用功能,不需要自定义编码,只需要在服务注册阶段开启对应开关即可:
var builder = WebApplication.CreateBuilder(args); // 注册控制器服务时开启校验 builder.Services.AddControllers() .Configure<MvcOptions>(options => { // 开启后,所有标记[FromQuery]绑定的复杂类型,会自动校验传入的查询参数是否全部映射到模型属性 // 存在未识别的参数时自动写入ModelState错误,配合默认ApiBehavior规则返回400响应 options.ValidateAllQueryParametersAreBound = true; });
注意点:
- 该开关默认值为
false,需要手动开启 - 校验逻辑会自动识别模型属性上通过
[FromQuery(Name = "别名")]指定的参数别名,不会出现误判 - 校验默认采用大小写不敏感规则,和框架默认的参数绑定规则一致
- 只要没有手动关闭
ApiBehaviorOptions.SuppressModelStateInvalidFilter(默认是关闭状态,即模型校验失败自动返回400),不需要额外配置其他逻辑,非法参数传入时会自动返回包含错误明细的400响应,错误信息会明确提示哪个参数未被识别。
.NET 6 及更早版本(无原生支持,需自定义过滤器)
.NET 6及更低版本没有提供对应的内置能力,可通过自定义全局动作过滤器实现校验逻辑,代码如下:
- 首先定义校验过滤器:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using System.Reflection; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class StrictQueryParameterValidationAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { var request = context.HttpContext.Request; // 遍历所有动作参数,找到绑定源为Query的复杂类型参数 foreach (var parameter in context.ActionDescriptor.Parameters.OfType<ControllerParameterDescriptor>()) { if (parameter.BindingInfo?.BindingSource != BindingSource.Query) continue; if (!context.ActionArguments.TryGetValue(parameter.Name, out var model) || model == null) continue; // 收集所有合法的参数名:包含属性名,以及[FromQuery]指定的别名 var validNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (var prop in model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { validNames.Add(prop.Name); var queryAttr = prop.GetCustomAttribute<FromQueryAttribute>(); if (!string.IsNullOrEmpty(queryAttr?.Name)) { validNames.Add(queryAttr.Name); } } // 检查所有传入的查询参数 foreach (var queryKey in request.Query.Keys) { if (!validNames.Contains(queryKey)) { context.ModelState.AddModelError(queryKey, $"参数{queryKey}为非法查询参数,不存在对应定义"); } } } base.OnActionExecuting(context); } }
- 全局注册过滤器,不需要在每个接口上单独加:
builder.Services.AddControllers(options => { options.Filters.Add<StrictQueryParameterValidationAttribute>(); });
这个自定义实现的逻辑和.NET 7+原生逻辑一致,支持参数别名识别、大小写不敏感校验,出现非法参数时同样会触发默认的400响应逻辑。
内容的提问来源于stack exchange,提问作者Developer Guy
相关产品推荐
相关产品推荐

