ASP.NET Core路由可选参数疑问:未传参时RouteValues为何不含id键
ASP.NET Core路由可选参数的工作机制解析
问题场景
你定义了如下包含可选参数的路由:
app.Map("products/details/{id?}", async context => { if (context.Request.RouteValues.ContainsKey("id")) { string? idValue = context.Request.RouteValues["id"] as string; bool isInt = long.TryParse(idValue, out long id); if (isInt) { await context.Response.WriteAsync($"Products details - {id}"); } else { await context.Response.WriteAsync("Needs to be a number"); } } else { await context.Response.WriteAsync("Products details - id is not supplied."); } });
预期未提供id时,RouteValues中仍保留id键且值为null,但实际ContainsKey("id")返回false,触发else代码块。
机制解析
在ASP.NET Core路由系统中,带?的可选路由参数未被提供时,不会被加入RouteValues集合,这是路由匹配的设计规则:
- 当访问
products/details时,路由系统匹配的是去掉可选参数段的路径模板,此时该可选参数并未参与匹配过程,因此不会在RouteValues中生成对应的键值对; - 只有当URL中存在对应参数段的内容(比如
products/details/123)时,路由系统才会将id键和对应值加入RouteValues。
优化处理方案
不用提前判断ContainsKey,直接从RouteValues取值即可——不存在的键会返回null,可以简化代码:
app.Map("products/details/{id?}", async context => { string? idValue = context.Request.RouteValues["id"] as string; if (!string.IsNullOrEmpty(idValue) && long.TryParse(idValue, out long id)) { await context.Response.WriteAsync($"Products details - {id}"); } else if (!string.IsNullOrEmpty(idValue)) { await context.Response.WriteAsync("Needs to be a number"); } else { await context.Response.WriteAsync("Products details - id is not supplied."); } });
如果需要强制RouteValues中始终存在id键,可以给可选参数设置默认值,修改路由模板为:
products/details/{id:long?=0}
此时未传参时RouteValues["id"]会返回默认值0,对应的键也会存在,适合需要固定参数存在的业务场景。
内容的提问来源于Stack Exchange,提问作者Mohamed Taha
相关产品推荐
相关产品推荐

