Asp.Net MVC实现分页、检索、排序的核心思路
实现这三个功能的核心是将分页参数、检索关键词、排序字段和排序方向统一作为查询参数传递到后端,后端根据这些参数对数据源进行筛选、排序和分页截取,最后将处理后的数据和分页信息返回给视图渲染。

一、定义查询参数与返回模型
首先定义统一的查询参数模型,包含所有需要的查询条件,同时定义分页结果模型,用于封装返回给视图的数据。
// 查询参数模型
public class QueryParam
{
// 当前页码,默认第1页
public int PageIndex { get; set; } = 1;
// 每页显示条数,默认10条
public int PageSize { get; set; } = 10;
// 检索关键词,可为空
public string Keyword { get; set; }
// 排序字段,默认按Id排序
public string SortField { get; set; } = "Id";
// 排序方向,true为升序,false为降序
public bool IsAsc { get; set; } = true;
}
// 分页结果模型
public class PagedResult<T>
{
// 当前页数据集合
public List<T> Data { get; set; }
// 总数据条数
public int TotalCount { get; set; }
// 当前页码
public int PageIndex { get; set; }
// 每页条数
public int PageSize { get; set; }
// 总页数
public int TotalPages => PageSize == 0 ? 0 : (int)Math.Ceiling((double)TotalCount / PageSize);
}
二、控制器逻辑实现
控制器中接收查询参数,根据参数对数据源进行处理,这里以模拟的用户列表数据为例,实际项目中可替换为数据库查询逻辑。
public class UserController : Controller
{
// 模拟用户数据
private List<User> GetMockUsers()
{
List<User> users = new List<User>();
for (int i = 1; i <= 50; i++)
{
users.Add(new User
{
Id = i,
Name = "用户" + i,
Age = 20 + (i % 10),
CreateTime = DateTime.Now.AddDays(-i)
});
}
return users;
}
public ActionResult List(QueryParam param)
{
// 获取模拟数据
var users = GetMockUsers().AsQueryable();
// 检索逻辑:如果有关键词,筛选名称包含关键词的数据
if (!string.IsNullOrEmpty(param.Keyword))
{
users = users.Where(u => u.Name.Contains(param.Keyword));
}
// 排序逻辑:根据排序字段和方向排序
if (param.SortField == "Id")
{
users = param.IsAsc ? users.OrderBy(u => u.Id) : users.OrderByDescending(u => u.Id);
}
else if (param.SortField == "Age")
{
users = param.IsAsc ? users.OrderBy(u => u.Age) : users.OrderByDescending(u => u.Age);
}
else if (param.SortField == "CreateTime")
{
users = param.IsAsc ? users.OrderBy(u => u.CreateTime) : users.OrderByDescending(u => u.CreateTime);
}
// 获取总条数
int totalCount = users.Count();
// 分页逻辑:跳过前面的数据,取指定条数
var pageData = users.Skip((param.PageIndex - 1) * param.PageSize).Take(param.PageSize).ToList();
// 封装分页结果
PagedResult<User> result = new PagedResult<User>
{
Data = pageData,
TotalCount = totalCount,
PageIndex = param.PageIndex,
PageSize = param.PageSize
};
// 将查询参数传递给视图,用于保持查询状态
ViewBag.QueryParam = param;
return View(result);
}
}
// 用户模型
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public DateTime CreateTime { get; set; }
}
三、视图页面实现
视图页面需要包含检索表单、排序表头、数据列表和分页控件,同时要保持检索、排序、分页状态的联动。
@model PagedResult<User>
@{
QueryParam queryParam = ViewBag.QueryParam as QueryParam;
queryParam = queryParam ?? new QueryParam();
}
<h2>用户列表</h2>
<!-- 检索表单 -->
@using (Html.BeginForm("List", "User", FormMethod.Get))
{
<p>
检索关键词:@Html.TextBox("Keyword", queryParam.Keyword)
<input type="submit" value="检索" />
<input type="hidden" name="SortField" value="@queryParam.SortField" />
<input type="hidden" name="IsAsc" value="@queryParam.IsAsc.ToString().ToLower()" />
<input type="hidden" name="PageIndex" value="1" />
</p>
}
<!-- 数据表格 -->
<table border="1" cellpadding="10" cellspacing="0">
<thead>
<tr>
<th>
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = "Id", IsAsc = (queryParam.SortField != "Id" ? true : !queryParam.IsAsc), PageIndex = 1, PageSize = queryParam.PageSize })">
Id @(queryParam.SortField == "Id" ? (queryParam.IsAsc ? "↑" : "↓") : "")
</a>
</th>
<th>名称</th>
<th>
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = "Age", IsAsc = (queryParam.SortField != "Age" ? true : !queryParam.IsAsc), PageIndex = 1, PageSize = queryParam.PageSize })">
年龄 @(queryParam.SortField == "Age" ? (queryParam.IsAsc ? "↑" : "↓") : "")
</a>
</th>
<th>
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = "CreateTime", IsAsc = (queryParam.SortField != "CreateTime" ? true : !queryParam.IsAsc), PageIndex = 1, PageSize = queryParam.PageSize })">
创建时间 @(queryParam.SortField == "CreateTime" ? (queryParam.IsAsc ? "↑" : "↓") : "")
</a>
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Data)
{
<tr>
<td>@item.Id</td>
<td>@item.Name</td>
<td>@item.Age</td>
<td>@item.CreateTime.ToString("yyyy-MM-dd HH:mm:ss")</td>
</tr>
}
</tbody>
</table>
<!-- 分页控件 -->
<p>
第 @Model.PageIndex 页,共 @Model.TotalPages 页,总计 @Model.TotalCount 条数据
</p>
<p>
@if (Model.PageIndex > 1)
{
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = queryParam.SortField, IsAsc = queryParam.IsAsc, PageIndex = 1, PageSize = queryParam.PageSize })">首页</a>
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = queryParam.SortField, IsAsc = queryParam.IsAsc, PageIndex = Model.PageIndex - 1, PageSize = queryParam.PageSize })">上一页</a>
}
@if (Model.PageIndex < Model.TotalPages)
{
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = queryParam.SortField, IsAsc = queryParam.IsAsc, PageIndex = Model.PageIndex + 1, PageSize = queryParam.PageSize })">下一页</a>
<a href="@Url.Action("List", new { Keyword = queryParam.Keyword, SortField = queryParam.SortField, IsAsc = queryParam.IsAsc, PageIndex = Model.TotalPages, PageSize = queryParam.PageSize })">末页</a>
}
</p>
四、注意事项
- 检索、排序、分页的参数需要互相传递,避免切换分页时丢失检索条件或排序状态
- 排序字段需要做合法性校验,防止用户传入不存在的字段导致程序报错
- 分页时如果总条数为0,需要隐藏分页控件,避免显示异常
- 实际项目中数据库查询建议使用ORM的分页、排序功能,避免一次性加载全部数据到内存
Asp.Net_MVC分页检索排序修改时间:2026-07-17 01:36:20