ASP.NET Core MVC 使用 X.PagedList.EF 实现分页、条件查询

参考

  • DeepSeek
  • 豆包
  • 其他(由于文章是后编写的,相关参考文章未存储连接)

环境

软件/系统 版本 说明
Windows windows 10 专业版 22H2 64 位操作系统, 基于 x64 的处理器
Microsoft Visual Studio Community 2022 (64 位) - Current 版本 17.14.9
Visual Studio Code 1.102.2
Docker Engine v28.3.2 Docker 桌面工具
Docker 28.3.2
pgAdmin4 9.0 PostgreSQL 数据库管理软件
PostgreSQL 15
.NET 8
ASP.NET Core MVC ASP.NET Core MVC in .NET 8.0
Microsoft.EntityFrameworkCore.Design 8.0.18 nuget 依赖
Microsoft.EntityFrameworkCore.Tools 8.0.18 nuget 依赖
Microsoft.VisualStudio.Web.CodeGeneration.Design 8.0.7 nuget 依赖 (Microsoft Visual Studio在通过模型生成控制器与视图时自动安装的依赖)
Npgsql.EntityFrameworkCore.PostgreSQL 8.0.11 nuget 依赖
EFCore.NamingConventions 8.0.3 nuget 依赖
X.PagedList.EF 10.5.7 nuget 依赖
X.PagedList.Mvc.Core 10.5.7 nuget 依赖(安装 X.PagedList.EF 时自动安装)

本项目入口文件为 Program.cs ,创建项目时为不使用顶级语句

正文

  1. 安装 X.PagedList.EF
  2. 模型 AdminModel.cs 内容:
    using Microsoft.EntityFrameworkCore;
    using NightMarketPlatformWeb.Enums;
    using System;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace NightMarketPlatformWeb.Models
    {
    	/// <summary>
    	/// 管理员管理模型
    	/// </summary>
    	[Table("admins")]
    	// 表备注
    	[Comment("管理员管理表")]
    	// 普通索引
    	//[Index(nameof(AreaName))]
    	// 普通索引并命名
    	//[Index(nameof(AreaName), Name = "AreaName")]
    	// 唯一索引
    	[Index(nameof(AdminName, IsUnique = true))]
    	// 复合唯一索引
    	[Index(nameof(AdminName), nameof(AdminPhoneNumber), IsUnique = true)]
    	public class AdminModel : BaseModel
    	{
    		/// <summary>
    		/// 主键
    		/// </summary>
    		[Key]
    		public int Id { get; set; }
    
    		/// <summary>
    		/// 管理员名称
    		/// </summary>
    		[Required]
    		// 字段备注
    		[Comment("管理员名称")]
    		// 显示名称
    		[Display(Name = "管理员名称")]
    		public string AdminName { get; set; } = string.Empty;
    
    		/// <summary>
    		/// 管理员账号/管理员联系方式
    		/// </summary>
    		[Required]
    		// 字段备注
    		[Comment("管理员账号/联系方式")]
    		// 显示名称
    		[Display(Name = "管理员账号/联系方式")]
    		public string AdminPhoneNumber { get; set; } = string.Empty;
    
    		/// <summary>
    		/// 管理员密码
    		/// </summary>
    		[Required]
    		// 长度验证 (如果这里设置了就会导致数据表出问题,把校验放到修改dto中)
    		//[StringLength(16, MinimumLength = 8, ErrorMessage = " {0} 区间为 {1} - {2}.")]
    		// 字段备注
    		[Comment("管理员密码")]
    		// 显示名称
    		[Display(Name = "管理员密码")]
    		public string AdminPassword { get; set; } = string.Empty;
    
    		/// <summary>
    		/// 是否启用
    		/// </summary>
    		// 字段备注
    		[Comment("是否启用")]
    		// 显示名称
    		[Display(Name = "是否启用")]
    		public bool Enabled { get; set; } = true;
    
    	}
    
    	public class BaseModel
    	{
    		/// <summary>
    		/// 创建时间
    		/// </summary>
    		[DataType(DataType.DateTime)]
    		// 字段备注
    		[Comment("创建时间")]
    		// 显示名称
    		[Display(Name = "创建时间")]
    		// 只在插入时填充
    		//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    		public DateTime CreatedTime { get; set; }
    		/// <summary>
    		/// 更新时间
    		/// </summary>
    		[DataType(DataType.DateTime)]
    		// 显示名称
    		[Display(Name = "更新时间")]
    		// 字段备注
    		[Comment("更新时间")]
    		// 每次更新时填充
    		//[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    		public DateTime UpdatedTime { get; set; }
    		/// <summary>
    		/// 删除时间
    		/// </summary>
    		[DataType(DataType.DateTime)]
    		// 显示名称
    		[Display(Name = "删除时间")]
    		// 字段备注
    		[Comment("删除时间")]
    		public DateTime? DeletedTime { get; set; }
    	}
    }
    
  3. 创建 AdminRequestDto.cs,接收分页参数、查询条件
    using System.ComponentModel.DataAnnotations;
    
    namespace NightMarketPlatformWeb.Dtos.Area
    {
    	/// <summary>
    	/// 请求DTO类
    	/// </summary>
    	public class AdminRequestDto : PaginationParamsDto
    	{
    		[Display(Name = "管理员名称")]
    		public string? AdminName { get; set; }
    	}
    	// 此类可以单独放到一个文件中声明,作为基础类传入
    	public class PaginationParamsDto
    	{
    		[Display(Name = "当前所在页")]
    		public int PageIndex { get; set; } = 1; // 默认第1页
    
    		[Display(Name = "每页显示数量")]
    		[Range(1, 100, ErrorMessage = "{0}不符合要求")]
    		public int PageSize { get; set; } = 10; // 默认每页10条
    	}
    }
    
  4. 创建 ResponseViewModel.cs,作为传输到视图的模型。(该实现仅供参考)
    namespace NightMarketPlatformWeb.ViewModels
    {
    	public class ResponseViewModel<P,VD>
    	{
    		public P Paramers { get; } = default!;
    		public VD ViewData { get; } = default!;
    
    		public ResponseViewModel(P req)
    		{
    			Paramers = req;
    		}
    
    		public ResponseViewModel(VD view)
    		{
    			ViewData = view;
    		}
    
    		public ResponseViewModel(P req, VD view) {
    			Paramers    = req;
    			ViewData = view;
    		}
    
    
    	}
    }
    
  5. 在控制器内编写相关逻辑,在查询条件拼写完毕后,使用ToPagedListAsync进行查询。
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Authentication.Cookies;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using NightMarketPlatformWeb.Data;
    using NightMarketPlatformWeb.Dtos.Admin;
    using NightMarketPlatformWeb.Dtos.Area;
    using NightMarketPlatformWeb.Models;
    using NightMarketPlatformWeb.Utils;
    using NightMarketPlatformWeb.ViewModels;
    using System.Security.Claims;
    using X.PagedList;
    using X.PagedList.EF;
    
    namespace NightMarketPlatformWeb.Controllers
    {
    	//当前文章讲解的是分页功能,权限功能注释
    	//[Authorize(Roles = "Admin")]
    	public class AdminController : Controller
    	{
    		private readonly ApplicationDbContext _context;
    
    		public AdminController(ApplicationDbContext context)
    		{
    			_context = context;
    		}
    		// GET: AdminModel
    		public async Task<IActionResult> Index(AdminRequestDto requestDto)
    		{
    			// 在数据库中操作,而不是内存
    			var query = _context.Admins.AsQueryable();
    			if (!string.IsNullOrEmpty(requestDto.AdminName))
    			{
    				query = query.Where(a => a.AdminName.Contains(requestDto.AdminName));
    			}
    			var datas = await query.OrderBy(d => d.Id).ToPagedListAsync(requestDto.PageIndex, requestDto.PageSize);
    
    			return View(new ResponseViewModel<AdminRequestDto, IPagedList<AdminModel>>(requestDto, datas));
    		}
    	}
    }
    
  6. 在视图内编写相关逻辑。
    @using NightMarketPlatformWeb.Dtos.Area
    @using NightMarketPlatformWeb.ViewModels
    @using X.PagedList
    @using X.PagedList.Mvc.Core
    @model ResponseViewModel<AdminRequestDto, IPagedList<AdminModel>>
    @{
    	ViewData["Title"] = "管理员";
    }
    
    <h1>列表页</h1>
    
    <p>
    	<a asp-action="Create">新增</a>
    </p>
    <form>
    	<p>
    		<label>@Html.DisplayNameFor(Model => Model.Paramers.AdminName): <input type="text" name="AdminName" value="@Model.Paramers.AdminName" /></label>
    		<input type="submit" class="btn btn-primary" value="搜索" />
    		<a asp-action="Index" class="btn">重置</a>
    	</p>
    </form>
    <table class="table">
    	<thead>
    		<tr>
    			<th>
    				管理员名称
    			</th>
    			<th>
    				管理员手机
    			</th>
    			<th>
    				是否启用
    			</th>
    			<th>
    				创建时间
    			</th>
    			<th>
    				更新时间
    			</th>
    			<th>操作</th>
    		</tr>
    	</thead>
    	<tbody>
    @foreach (var item in Model.ViewData) {
    		<tr>
    			<td>
    				@Html.DisplayFor(modelItem => item.AdminName)
    			</td>
    			<td>
    				@Html.DisplayFor(modelItem => item.AdminPhoneNumber)
    			</td>
    			<td>
    				@Html.DisplayFor(modelItem => item.Enabled)
    			</td>
    			<td>
    				@Html.DisplayFor(modelItem => item.CreatedTime)
    			</td>
    			<td>
    				@Html.DisplayFor(modelItem => item.UpdatedTime)
    			</td>
    			<td>
    				<a asp-action="Edit" asp-route-id="@item.Id">编辑</a> |
    				<a asp-action="Details" asp-route-id="@item.Id">查看</a> |
    				<a asp-action="Delete" asp-route-id="@item.Id">删除</a>
    			</td>
    		</tr>
    }
    	</tbody>
    </table>
    @Html.PagedListPager(
    		Model.ViewData, 
    		// 使用分页控件提供的page参数(当前点击的页码)作为pageIndex的值
    		page => Url.Action("Index", new { pageIndex = page,pageSize=Model.Paramers.PageSize,adminName= Model.Paramers.AdminName }),
    		new PagedListRenderOptions {
    			LiElementClasses = new[] { "page-item" },
    			PageClasses = new[] { "page-link" }
    		}
     )
    

预览

  • 生成结果参考
    image
posted @ 2025-07-27 18:05  夏秋初  阅读(51)  评论(0)    收藏  举报