Dictionary替代方案:ASP.NET Core中重复键与asp-all-route-data适配问题
核心问题
执行CurrentFilters.Add($"Colors", Colors[i].ToString());时触发重复键错误,因为Dictionary<string, string>不允许同一键多次添加;而asp-all-route-data仅支持IDictionary<string, string>类型,无法直接生成Colors=red&Colors=blue这类多值URL参数,同时模型绑定要求键名为Colors才能正确接收多值列表。
解决方案
方案1:自定义扩展方法生成多值查询字符串
放弃直接使用asp-all-route-data,通过扩展方法将多值字典转换为符合要求的查询字符串:
修改后端模型属性类型
将CurrentFilters改为Dictionary<string, List<string>>,用于存储多值参数:public Dictionary<string, List<string>> CurrentFilters { get; set; } = new();在
OnGetAsync中添加参数时,直接向对应键的列表中添加值:// 初始化单值参数 CurrentFilters["SearchString"] = new List<string> { SearchString }; CurrentFilters["SortOrder"] = new List<string> { SortOrder }; // 添加多值Colors if (Colors != null && Colors.Any()) { CurrentFilters["Colors"] = Colors.ToList(); }添加查询字符串生成扩展方法
创建静态类实现字典转查询字符串的逻辑,处理多值参数:public static class RouteDataExtensions { public static string ToQueryString(this Dictionary<string, List<string>> routeData) { var queryItems = new List<string>(); foreach (var kvp in routeData) { foreach (var value in kvp.Value.Where(v => !string.IsNullOrEmpty(v))) { queryItems.Add($"{Uri.EscapeDataString(kvp.Key)}={Uri.EscapeDataString(value)}"); } } return queryItems.Any() ? $"?{string.Join("&", queryItems)}" : string.Empty; } }前端使用扩展方法生成URL
在<a>标签中直接调用扩展方法生成完整查询字符串:<a href="/Index@Model.CurrentFilters.ToQueryString()">应用筛选</a>此方式会生成目标格式的URL:
localhost234/Index?SearchString=text&Colors=red&Colors=blue&SortOrder=Colors_asc,后端List<string> Colors属性可直接完成模型绑定。
方案2:使用QueryBuilder构造查询字符串
若不想修改CurrentFilters的类型,可通过QueryBuilder手动拼接包含多值的查询参数:
后端构造查询字符串
在OnGetAsync中生成查询字符串并存储到模型属性:public string FilterQueryString { get; set; } public async Task OnGetAsync() { var queryBuilder = new QueryBuilder(); // 添加单值参数 if (!string.IsNullOrEmpty(SearchString)) { queryBuilder.Add("SearchString", SearchString); } if (!string.IsNullOrEmpty(SortOrder)) { queryBuilder.Add("SortOrder", SortOrder); } // 添加多值Colors if (Colors != null && Colors.Any()) { foreach (var color in Colors) { queryBuilder.Add("Colors", color); } } FilterQueryString = queryBuilder.ToString(); }前端直接使用生成的查询字符串
<a href="/Index@Model.FilterQueryString">应用筛选</a>
关键说明
asp-all-route-data仅支持IDictionary<string, string>,无法生成同一键的多个参数,因此必须通过自定义逻辑绕过此限制。- 后端模型中需声明
List<string> Colors属性,ASP.NET Core会自动将URL中多个Colors参数绑定到该列表。
内容的提问来源于stack exchange,提问作者dave

