C#开发API时如何获取并解析URL查询字符串参数
ASP.NET Core 原生支持查询字符串参数自动绑定,不需要额外配置端点或第三方组件。你当前只能通过/分隔的路径传参,本质是两个配置错误导致的:
- 全局路由模板里提前定义了大量可选路径参数占位(
{id?}/{id1?}...{id6?}),干扰了默认绑定逻辑 - 接口的
[HttpGet]/[HttpPost]特性中,把所有参数都写进了路由模板作为路径段,框架会优先匹配路径参数,不会从查询字符串读取
1. 修正全局路由配置
删掉全局路由里冗余的可选路径参数定义,WebAPI场景推荐直接使用特性路由自动匹配,不要在全局层面预定义参数段:
app.UseEndpoints(endpoints => { // 适配带[ApiController]特性的RESTful控制器,自动识别接口上声明的路由规则 endpoints.MapControllers(); });
如果你要保留传统路由配置,也只需要定义到控制器层即可,不要预定义参数:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "api/v1/{controller}/{action?}"); });
2. 调整接口路由模板,按需求选择参数绑定来源
路由模板里只保留需要通过/路径传递的参数段,其余不需要走路径的参数不要写在路由模板里,加上[FromQuery]特性即可强制从查询字符串绑定。
示例1:GET接口所有参数走查询字符串
你希望customerId通过查询字符串传递,如果要匹配你写的http://localhost:0000/api/v1?customerId=1地址,就把路由模板固定为/api/v1,不要加任何参数占位:
[HttpGet("/api/v1")] public List<string> GetTemplates([FromQuery] string customerId) { return templatesService.GetTemplates(customerId); }
如果遵循RESTful规范保留资源路径段(Templates为资源名),就把路由模板改成/api/v1/Templates,对应请求地址为http://localhost:0000/api/v1/Templates?customerId=1。
示例2:POST接口指定参数走查询字符串
你提到templateName、singleOptions、multiOptions都需要走查询字符串,就把路由模板固定为资源路径,所有参数标记[FromQuery]:
[HttpPost("/api/v1/Templates")] public string GetReplacedTemplate( [FromQuery] string customerId, [FromQuery] string templateName, [FromQuery] string singleOptions, [FromQuery] string multiOptions) { return templatesService.GetReplacedTempalte(customerId, templateName, singleOptions, multiOptions); }
如果你需要保留部分参数走路径,比如让customerId作为路径段、其余参数走查询字符串,只需要在路由模板里保留对应参数占位即可,其余参数照旧标记[FromQuery]:
// 对应请求格式:POST /api/v1/Templates/1?templateName=订单通知&singleOptions=xxx&multiOptions=yyy [HttpPost("/api/v1/Templates/{customerId}")] public string GetReplacedTemplate( string customerId, // 路由模板有同名占位,自动从路径绑定 [FromQuery] string templateName, [FromQuery] string singleOptions, [FromQuery] string multiOptions) { return templatesService.GetReplacedTempalte(customerId, templateName, singleOptions, multiOptions); }
ASP.NET Core 对string、int、bool等简单类型参数的默认绑定逻辑如下:
- 如果路由模板中存在同名参数占位,优先从URL路径绑定参数
- 如果路由模板中无同名参数占位,优先从查询字符串绑定参数
- 标记
[FromQuery]特性的参数,会强制从查询字符串读取,此时如果路由模板中还保留同名路径占位,会导致路由匹配失败,记得同步删除路由模板里的对应参数段 - POST请求如果同时需要接收JSON请求体和查询字符串参数,只需要给实体类参数加
[FromBody]、查询字符串参数加[FromQuery],两者不会冲突
内容的提问来源于stack exchange,提问作者ThisQRequiresASpecialist

