如何在ASP.NET的JsonResult方法中实现分页并向HTML视图的Ajax返回结果?
在ASP.NET中用JsonResult实现分页并通过Ajax返回给视图
嘿,这个需求我帮不少开发者落地过,其实拆解开来分后端和前端两部分就能轻松搞定,咱们一步一步来:
1. 后端实现(C#/ASP.NET)
首先得把分页需要的核心数据封装起来,这样前端能拿到完整的分页上下文,比如当前页数据、总页数、总记录数这些。
1.1 定义通用分页结果模型
先搞个泛型类,不管你返回什么类型的数据都能复用:
public class PagedResult<T> { // 当前页的数据列表 public List<T> Data { get; set; } // 总记录数 public int TotalRecords { get; set; } // 当前页码(从1开始计数更符合用户习惯) public int CurrentPage { get; set; } // 每页条数 public int PageSize { get; set; } // 计算总页数,用Math.Ceiling确保向上取整 public int TotalPages => (int)Math.Ceiling((double)TotalRecords / PageSize); }
1.2 编写返回JsonResult的Action方法
假设你要做产品列表的分页,这里用EF Core举例(换成其他数据源逻辑也类似):
public JsonResult GetPagedProducts(int page = 1, int pageSize = 10) { // 先做参数校验,避免非法请求 page = Math.Max(1, page); pageSize = Math.Clamp(pageSize, 1, 50); // 限制每页最多50条,防止恶意拉取数据 using (var dbContext = new YourDbContext()) { // 获取总记录数 var totalCount = dbContext.Products.Count(); // 分页查询:跳过前面(page-1)*pageSize条,取pageSize条数据,记得一定要排序! var pagedData = dbContext.Products .OrderBy(p => p.Id) .Skip((page - 1) * pageSize) .Take(pageSize) .ToList(); // 封装分页结果 var result = new PagedResult<Product> { Data = pagedData, TotalRecords = totalCount, CurrentPage = page, PageSize = pageSize }; // ASP.NET Core直接返回Json(result)即可;老版MVC需要加JsonRequestBehavior.AllowGet允许GET请求 return Json(result); } }
2. 前端Ajax实现(HTML视图)
前端主要负责发起请求、渲染数据和分页控件,这里用jQuery简化操作(原生JS或Vue/React逻辑也大同小异):
2.1 页面基础结构
先准备好展示数据和分页的容器:
<div id="productList"></div> <div id="paginationBar" style="margin-top: 15px;"></div>
2.2 Ajax请求与渲染逻辑
// 全局变量保存当前页码和每页条数 let currentPage = 1; const pageSize = 10; // 加载分页数据的核心函数 function loadPageData(pageNum) { $.ajax({ url: '/Home/GetPagedProducts', // 替换成你的控制器和Action路径 type: 'GET', data: { page: pageNum, pageSize: pageSize }, success: function(res) { // 渲染数据列表 renderProductList(res.Data); // 渲染分页控件 renderPagination(res); // 更新当前页码 currentPage = pageNum; }, error: function(xhr) { $('#productList').html('<p>加载数据失败,请稍后重试</p>'); console.error('请求错误:', xhr.responseText); } }); } // 渲染产品列表 function renderProductList(products) { let listHtml = '<ul style="list-style: none; padding: 0;">'; products.forEach(prod => { listHtml += `<li style="padding: 8px; border-bottom: 1px solid #eee;">${prod.Name} - ¥${prod.Price}</li>`; }); listHtml += '</ul>'; $('#productList').html(listHtml); } // 渲染分页控件(简化版,可根据需求扩展样式) function renderPagination(pagedResult) { let paginationHtml = ''; // 上一页按钮 if (pagedResult.CurrentPage > 1) { paginationHtml += `<button onclick="loadPageData(${pagedResult.CurrentPage - 1})" style="margin: 0 2px;">上一页</button>`; } // 页码按钮:显示当前页前后各2页,避免页码过多 const startPage = Math.max(1, pagedResult.CurrentPage - 2); const endPage = Math.min(pagedResult.TotalPages, pagedResult.CurrentPage + 2); for (let i = startPage; i <= endPage; i++) { if (i === pagedResult.CurrentPage) { paginationHtml += `<button disabled style="background: #007bff; color: white; margin: 0 2px;">${i}</button>`; } else { paginationHtml += `<button onclick="loadPageData(${i})" style="margin: 0 2px;">${i}</button>`; } } // 下一页按钮 if (pagedResult.CurrentPage < pagedResult.TotalPages) { paginationHtml += `<button onclick="loadPageData(${pagedResult.CurrentPage + 1})" style="margin: 0 2px;">下一页</button>`; } // 附加统计信息 paginationHtml += `<span style="margin-left: 10px;">共${pagedResult.TotalRecords}条,${pagedResult.TotalPages}页</span>`; $('#paginationBar').html(paginationHtml); } // 页面加载完成后默认加载第一页 $(document).ready(() => { loadPageData(1); });
3. 一些实用小提示
- 排序必加:分页查询一定要加
OrderBy,否则数据库返回的顺序不稳定,分页结果会混乱。 - 参数校验:后端对
page和pageSize做校验,防止非法参数导致的异常。 - 性能优化:如果数据量极大,可考虑缓存总记录数,避免每次分页都执行
Count()。
内容的提问来源于stack exchange,提问作者Rawan
相关产品推荐
相关产品推荐

