前言

小伙伴们,

大家好,我是Rector。

最近Rector忙于换工作,没有太多时间来更新我们的ASP.NET MVC 5系列文章 [一步一步创建ASP.NET MVC5程序Repository+Autofac+Automapper+SqlSugar],直到现在才挤些时间赶紧更新一篇,小伙伴们等得太久了。

写系列文章是一件并不容易的事情,相信有过写系列文章经验朋友也应该有所体会。

本文知识要点

本期是该系列的第十一篇,上一篇《一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](十)》我们了解了母版页和部分视图,并使用母版页和部分视图重新组织了页面的共用区域的HTML代码,本文我们将要涉及到的内容为:

  • 通用分页的封装
  • 文章分页的实现

通用分页的封装

在之前两期中,我们的文章列表页面是没有分页功能的,而是使用如下方法:

public IEnumerable<Post> FindHomePagePosts(int limit = 20)
{
using (var db = DbFactory.GetSqlSugarClient())
{
var list = db.Queryable<Post>().OrderBy(x => x.Id, OrderByType.Desc).Take(limit).ToList();
return list;
}
}

来读取文章表中的前N(20)条记录作为首页的文章列表数据源。那么,本文将为大家封装一个通用的分页信息类以及分页泛型方法,并最终实现首页文章列表的数据分页功能。分页效果如下图:

创建IPagedList接口及实现

打开项目TsBlog.Repositories,在此项目中分别新建两个类:IPagedList.csPagedList.cs,代码分别如下:

IPagedList.cs

using System.Collections.Generic;

namespace TsBlog.Repositories
{
public interface IPagedList<T> : IList<T>
{
int PageIndex { get; }
int PageSize { get; }
int TotalCount { get; }
int TotalPages { get; }
bool HasPreviousPage { get; }
bool HasNextPage { get; }
}
}

IPagedLIst.cs

using System;
using System.Collections.Generic;
using System.Linq; namespace TsBlog.Repositories
{
/// <summary>
/// 分页组件实体类
/// </summary>
/// <typeparam name="T">泛型实体</typeparam> [Serializable]
public class PagedList<T> : List<T>, IPagedList<T>
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="source">数据源</param>
/// <param name="pageIndex">分页索引</param>
/// <param name="pageSize">分页大小</param>
public PagedList(IQueryable<T> source, int pageIndex, int pageSize)
{
var total = source.Count();
TotalCount = total;
TotalPages = total / pageSize; if (total % pageSize > 0)
TotalPages++; PageSize = pageSize;
PageIndex = pageIndex; AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="source">数据源</param>
/// <param name="pageIndex">分页索引</param>
/// <param name="pageSize">分页大小</param>
public PagedList(IList<T> source, int pageIndex, int pageSize)
{
TotalCount = source.Count();
TotalPages = TotalCount / pageSize; if (TotalCount % pageSize > 0)
TotalPages++; PageSize = pageSize;
PageIndex = pageIndex;
AddRange(source.Skip(pageIndex * pageSize).Take(pageSize).ToList());
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="source">数据源</param>
/// <param name="pageIndex">分页索引</param>
/// <param name="pageSize">分页大小</param>
/// <param name="totalCount">总记录数</param>
public PagedList(IEnumerable<T> source, int pageIndex, int pageSize, int totalCount)
{
TotalCount = totalCount;
TotalPages = TotalCount / pageSize; if (TotalCount % pageSize > 0)
TotalPages++; PageSize = pageSize;
PageIndex = pageIndex;
AddRange(source);
} /// <summary>
/// 分页索引
/// </summary>
public int PageIndex { get; }
/// <summary>
/// 分页大小
/// </summary>
public int PageSize { get; private set; }
/// <summary>
/// 总记录数
/// </summary>
public int TotalCount { get; }
/// <summary>
/// 总页数
/// </summary>
public int TotalPages { get; } /// <summary>
/// 是否有上一页
/// </summary>
public bool HasPreviousPage
{
get { return (PageIndex > 0); }
}
/// <summary>
/// 是否有下一页
/// </summary>
public bool HasNextPage
{
get { return (PageIndex + 1 < TotalPages); }
}
}
}

其中,IPagedList.cs为一个分页信息接口,包含了分页的基本信息,如:当前页索引(PageIndex),分页大小(PageSize),总记录数(TotalCount),总页数(TotalPages)等等。而PagedList.cs类文件则是对IPagedList.cs接口的实现。

添加泛型仓储分页接口

打开项目TsBlog.RepositoriesIRepository.cs 文件,在其中新建分页接口,如下:

/// <summary>
/// 根据条件查询分页数据
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBy"></param>
/// <param name="pageIndex">当前页面索引</param>
/// <param name="pageSize">分布大小</param>
/// <returns></returns>
IPagedList<T> FindPagedList(Expression<Func<T, bool>> predicate, string orderBy = "", int pageIndex = 1, int pageSize = 20);

再打开此项目中的 GenericRepository.cs 泛型仓储实现类,在其中实现FindPagedList这个分页方法,如下:

/// <summary>
/// 根据条件查询分页数据
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBy"></param>
/// <param name="pageIndex">当前页面索引</param>
/// <param name="pageSize">分布大小</param>
/// <returns></returns>
public IPagedList<T> FindPagedList(Expression<Func<T, bool>> predicate, string orderBy = "", int pageIndex = 1, int pageSize = 20)
{
using (var db = DbFactory.GetSqlSugarClient())
{
var totalCount = 0;
var page = db.Queryable<T>().OrderBy(orderBy).ToPageList(pageIndex, pageSize, ref totalCount);
var list = new PagedList<T>(page, pageIndex, pageSize, totalCount);
return list;
}
}

类似地操作,打开项目 TsBlog.Services,并打开文件 IService.cs,在其中添加分页服务接口,如下:

/// <summary>
/// 根据条件查询分页数据
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBy"></param>
/// <param name="pageIndex">当前页面索引</param>
/// <param name="pageSize">分布大小</param>
/// <returns></returns>
IPagedList<T> FindPagedList(Expression<Func<T, bool>> predicate, string orderBy = "", int pageIndex = 1, int pageSize = 20);

再打开此项目中的泛型服务类GenericService.cs,在其中实现分页服务接口,如下:

/// <summary>
/// 根据条件查询分页数据
/// </summary>
/// <param name="predicate"></param>
/// <param name="orderBy"></param>
/// <param name="pageIndex">当前页面索引</param>
/// <param name="pageSize">分布大小</param>
/// <returns></returns>
public IPagedList<T> FindPagedList(Expression<Func<T, bool>> predicate, string orderBy = "", int pageIndex = 1, int pageSize = 20)
{
return _repository.FindPagedList(predicate, orderBy, pageIndex, pageSize);
}

到此,我们的泛型仓储和服务的通用分页接口和实现就封装完成了,现在我们需要使用以上的分页封装,在UI层来实现文章列表的分页功能。

**切换到项目 TsBlog.Frontend **。

安装第三方分页组件

为了方便,本示例教程使用的是第三方的分页组件来实现UI层的分页功能,组件为:PagedList。安装的方式为:nuget,所以与以前几期的nuget包安装类似,打开nuget包管理工具,搜索关键词PagedList,在查询出来的包中,选择PagedList.MvcPagedList两个分页组件包并安装,如下:

分页组件安装完成之后,我们再打开 HomeController 控制器,修改Index这个ActionHomerController.cs修改后的完整代码如下:

using PagedList;
using System.Linq;
using System.Web.Mvc;
using TsBlog.AutoMapperConfig;
using TsBlog.Frontend.Extensions;
using TsBlog.Services;
using TsBlog.ViewModel.Post; namespace TsBlog.Frontend.Controllers
{
public class HomeController : Controller
{
/// <summary>
/// 文章服务接口
/// </summary>
private readonly IPostService _postService;
public HomeController(IPostService postService)
{
_postService = postService;
}
/// <summary>
/// 首页
/// </summary>
/// <returns></returns>
public ActionResult Index(int? page)
{
//var list = _postService.FindHomePagePosts();
//读取分页数据,返回IPagedList<Post>
page = page ?? 0;
var list = _postService.FindPagedList(x => !x.IsDeleted && x.AllowShow, pageIndex: (int)page, pageSize: 10);
var model = list.Select(x => x.ToModel().FormatPostViewModel());
ViewBag.Pagination = new StaticPagedList<PostViewModel>(model, list.PageIndex, list.PageSize, list.TotalCount);
return View(model);
}
}
}

最后,再打开Index对应的视图文件:/Views/Home/Index.cshtml,添加分页控件,如下:

@using PagedList
@using PagedList.Mvc
@model IEnumerable<TsBlog.ViewModel.Post.PostViewModel>
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "ASP.NET MVC 5 系列文章教程--首页";
}
<div class="jumbotron">
<h1>小伙伴,你好</h1>
<p>欢迎来到 Rector 的ASP.NET MVC 5 系列文章教程。在这里,Rector将和你一起一步一步创建一个集成Repository+Autofac+Automapper+SqlSugar的WEB应用程序。</p>
<p>你准备好了吗?</p>
<p>......</p>
<p>让我们开始ASP.NET MVC 5 应用程序的探索之旅吧!!!</p>
</div>
<strong class="post-title">文章列表(@(Model.Count())篇)</strong>
<ul class="list-unstyled post-item-box">
@foreach (var p in Model)
{
<li>
<h2><a href="~/post/details/@p.Id">@p.Title</a></h2>
<p class="post-item-summary">@p.Summary ... <a href="~/post/details/@p.Id">阅读全文</a></p>
</li>
}
</ul>
@Html.PagedListPager((IPagedList)ViewBag.Pagination, page => Url.Action("index", new { page }), new PagedListRenderOptions
{
LinkToFirstPageFormat = "首页",
LinkToPreviousPageFormat = "上一页",
LinkToNextPageFormat = "下一页",
LinkToLastPageFormat = "末页",
DisplayLinkToFirstPage = PagedListDisplayMode.IfNeeded,
DisplayLinkToLastPage = PagedListDisplayMode.Never,
DisplayEllipsesWhenNotShowingAllPageNumbers = true,
MaximumPageNumbersToDisplay = 5
})

以上所有更改完成后,就完成了我们对通用分页的封装和实现,当然,这个通用分页是非常简单的,只能满足单表数据的分页查询和读取。更复杂的分页需求请自行根据思路进行实现。

完成以上步骤之后,我们重新编译和生成项目 TsBlog.Frontend 。最后,在浏览器中打开地址: http://localhost:54739/ ,检查一下,数据分页功能是否起作用了呢?

好了,如果你喜欢Rector,或者是喜欢本系列文章,请为我点个赞,以鼓励Rectro继续写出更好的文章,或者系列文章。

本期源码托管地址:请至首发地址《一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](十一)》查看

看完教程如果觉得还不过瘾的,想“勾对”的,欢迎加入图享网官方QQ群:483350228,如果你按照教程还原出来的程序运行有问题,请参照本期源码对应调整与修改遇到问题的,也欢迎加入QQ群。有什么,你懂的。。。_

谢谢你的耐心阅读,本系列未完待续,我们下期再见……

同时,也欢迎大家关注我们的.NET编程爱好者社区:https://2sharings.com 每天都有.NET的开发技术干货更新哦。

[https://2sharings.com] 一个.NET编程爱好者社区,专注.NET/C#开发,帮助你找到疑难问题的更优美、更高级的解决方案

一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](十一)的更多相关文章

  1. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](一)

    前言 大家好,我是Rector 从今天开始,Rector将为大家推出一个关于创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]的文章系列, ...

  2. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)

    前言 Hi,大家好,我是Rector 时间飞逝,一个星期又过去了,今天还是星期五,Rector在图享网继续跟大家分享系列文本:一步一步创建ASP.NET MVC5程序[Repository+Autof ...

  3. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](四)

    前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)>,我们完成了: * 引用SqlSugar * ...

  4. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)

    前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](二)>我们通过如下操作: 创建实体及工具类 创建Re ...

  5. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](二)

    前言: 在本系列第一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](一)>中,我为大家介绍了搭建空白解决方案以 ...

  6. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](六)

    前言 大家好,我是Rector 又是星期五,很兴奋,很高兴,很high...啦啦啦... Rector在图享网又和大家见面啦!!!上一篇<一步一步创建ASP.NET MVC5程序[Reposit ...

  7. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](七)

    前言 大家好,我依旧是你们的老朋友Rector,很高兴又在周五的时候准时和大家见面. Rector的系列文章[一步一步创建ASP.NET MVC5程序[Repository+Autofac+Autom ...

  8. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](八)

    前言 Hi, 大家好,还是星期五,还是Rector,又在图享网准时和大家见面了. 今天给大家带来系列教程<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Auto ...

  9. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](九)

    前言 童鞋们,大家好 我是专注.NET开发者社区建设的实践者Rector. 首先,为自己间隔了两个星期五再更新本系列文章找个不充分的理由:Rector最近工作,家庭的各种事务所致,希望大家谅解. 本文 ...

随机推荐

  1. elasticsearch节点(角色)类型解释node.master和node.data

    在生产环境下,如果不修改elasticsearch节点的角色信息,在高数据量,高并发的场景下集群容易出现脑裂等问题. 默认情况下,elasticsearch集群中每个节点都有成为主节点的资格,也都存储 ...

  2. iOS通知传值的使用

    通知 是在跳转控制器之间常用的传值代理方式,除了代理模式,通知更方便.便捷,一个简单的Demo实现通知的跳转传值. 输入所要发送的信息 ,同时将label的值通过button方法调用传递, - (IB ...

  3. 计蒜客 数字解码 dp

    思路:dp(i)表示前i个字符的解码方案种数.进行状态转移时需要仔细思考,分情况讨论: 设第i个字符和第i-1个字符组成的数为x. 1.如果x根本不可能出现说明不是合理的编码,直接使dp(i)为0,例 ...

  4. CodeForces - 730A 贪心+模拟

    贪心策略: 1.只有一个最大值,选着第二大的一起参加比赛减分. 2.有奇数个最大值,选择三个进行比赛. 3.偶数个最大值,选择两个进行比赛. 为什么不把最大值全部选择? 因为最多只能选五个,有可能选择 ...

  5. CodeForces - 740C

    这题是思维考察.由于区间个数可能会很多,暴力完全没法下手.首先要明确区间长度最小的就决定了最后的答案,因为最小区间必须要要从0开始到区间长度减1才能满足让mex最大.接下来就是考虑如何填充数组才能让所 ...

  6. Socket 参数笔记

    //服务端@RunWith(JUnit4.class) public class ServerSocketTest { @Test public void testServer() throws IO ...

  7. 跨域问题jsonp

    不得不说的同源政策: 同源策略,它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略.所谓同源是指域名,协议,端口相同.当一个浏览器的两个tab页 ...

  8. js数据类型的判断方法

    判断js中的数据类型有一下几种方法:typeof.instanceof. constructor. prototype. $.type()/jquery.type(),接下来主要比较一下这几种方法的异 ...

  9. FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

    FFMPEG中的swscale提供了视频原始数据(YUV420,YUV422,YUV444,RGB24...)之间的转换,分辨率变换等操作,使用起来十分方便,在这里记录一下它的用法. swscale主 ...

  10. 修正uboot网络不可用

    通过使用uboot的网络功能可以更新ubook,烧写内核,文件系统,如果网络功能不可能,那还不如同变砖了一样.当然如果支持sd卡启动,可能通过sd卡完成这些功能,但是也太过麻烦了.飞凌的6410开发板 ...