ASP.NET Core MVC中带筛选参数保留的分页实现问题
解决ASP.NET Core MVC分页时保留多参数筛选的问题
你的第二个方案出错的核心原因是:asp-route-*标签助手无法直接正确绑定List<string>类型的参数,它会将集合对象直接转为字符串(比如System.Collections.Generic.List1[System.String]),而不是生成多个同名的查询参数(如selectedCountries=USA&selectedCountries=UK`)。
下面提供两种可靠的实现方式:
方法1:使用asp-all-route-data传递所有参数
这种方式可以自动处理集合类型,无需手动逐个添加参数:
步骤1:在ViewModel中构建路由数据字典
在MovieViewModel中添加属性,将筛选参数和分页参数打包成RouteValueDictionary:
public record MovieViewModel { // 原有属性... public List<Movie> docs { get; set; } public int total { get; set; } public int limit { get; set; } public int page { get; set; } public int pages { get; set; } public MovieFilters movieFilters { get; set; } // 用于传递路由参数的字典 public RouteValueDictionary RouteData { get { var routeData = new RouteValueDictionary(); // 基础分页参数 routeData["page"] = page; // 遍历添加筛选集合参数 if (movieFilters?.Genres?.Any() == true) { foreach (var genre in movieFilters.Genres) routeData.Add("selectedGenres", genre); } if (movieFilters?.Countries?.Any() == true) { foreach (var country in movieFilters.Countries) routeData.Add("selectedCountries", country); } if (movieFilters?.Years?.Any() == true) { foreach (var year in movieFilters.Years) routeData.Add("selectedYears", year); } return routeData; } } }
步骤2:在视图中使用标签助手
分页链接修改为:
<li class="page-item @(Model.page >= Model.pages ? "disabled" : "")"> <a class="page-link" asp-controller="Home" asp-action="SearchByFilters" asp-all-route-data="@Model.RouteData" asp-route-page="@(Model.page + 1)"> Next </a> </li>
注:
asp-route-page会覆盖字典中的page值,确保传递下一页的页码。
方法2:手动构建查询字符串
如果不想修改ViewModel,可直接在视图中遍历筛选集合拼接参数:
@{ var queryParts = new List<string>(); // 添加下一页参数 queryParts.Add($"page={Model.page + 1}"); // 处理流派筛选 if (Model.MovieFilters?.Genres?.Any() == true) { queryParts.AddRange(Model.MovieFilters.Genres .Select(g => $"selectedGenres={Uri.EscapeDataString(g)}")); } // 处理国家筛选 if (Model.MovieFilters?.Countries?.Any() == true) { queryParts.AddRange(Model.MovieFilters.Countries .Select(c => $"selectedCountries={Uri.EscapeDataString(c)}")); } // 处理年份筛选 if (Model.MovieFilters?.Years?.Any() == true) { queryParts.AddRange(Model.MovieFilters.Years .Select(y => $"selectedYears={Uri.EscapeDataString(y)}")); } var nextPageUrl = $"/Home/SearchByFilters?{string.Join("&", queryParts)}"; } <li class="page-item @(Model.page >= Model.pages ? "disabled" : "")"> <a class="page-link" href="@nextPageUrl">Next</a> </li>
使用Uri.EscapeDataString可避免特殊字符导致的URL编码问题,保证参数传递准确。
额外优化建议
- 将分页逻辑封装为局部视图,减少重复代码;
- 控制器方法可改用
[FromQuery]直接绑定筛选对象,简化参数列表:
public async Task<IActionResult> SearchByFilters([FromQuery] MovieFilters filters, int page = 1) { var dataFromApi = await _kinopoiskApiService.GetMoviesByFilter(filters, page); // 后续逻辑不变 }
- 添加参数校验,比如限制
page不能小于1,避免无效请求。
内容的提问来源于stack exchange,提问作者Vitaliy
相关产品推荐
相关产品推荐

