第17章 分页与JQuery DataTables渲染显示

1 Services.Customers.CustomerService.GetAllCustomersAsync

 #region 方法--接口实现--用户

        /// <param name="deleted">指示是否包含指定实体中所有的逻辑删除项,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <param name="email">1个指定的电字邮箱字符串,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <param name="username">1个指定的用户名/昵称,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <param name="phone">1个指定的手机号,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <param name="createdDateFrom">1个指定的用户注册开始日期,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <param name="createdDateTo">>1个指定的用户注册结束日期,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <param name="pageIndex">当前页的页数值(“pageSize”结合,设定需要跳过指定实体实例的个数值),默认值:0,即不需要执行跳过操作。</param>

        /// <param name="pageSize">分页操作中每页最多显示实例的项()数值(“pageIndex”结合,设定需要跳过指定实体实例的个数值),默认值:int.MaxValue=2147483647</param>

        /// <param name="getOnlyTotalCount">指示数据源中否包含有实例,默认值:null,即该参数实例不参与筛选操作。</param>

        /// <summary>

        /// 【异步获取所有用户】

        /// <remarks>

        /// 摘要:

        ///     根据前端分页组件传递的参数实例,获取符合条件的用户表1指定页面内的持久化数据加载到1指定内存逻辑页面内。

        ///  说明:

        ///     该方法没有定义缓存操作,更没有定义缓存的移除操作。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    1指定内存逻辑页面内的用户实体的所有实例。

        /// </returns>

        /// </summary>

        public virtual async Task<IPagedList<Customer>> GetAllCustomersAsync(bool? deleted = null, string email = null, string username = null, string phone = null,

            DateTime? createdDateFrom = null, DateTime? createdDateTo = null, long pageIndex = 0, int pageSize = int.MaxValue, bool getOnlyTotalCount = false)

        {

            var customers = await _customerRepository.GetAllPagedAsync(query =>

            {

                if (deleted.HasValue)

                    query = query.Where(c => c.Deleted.Equals(deleted));

                if (createdDateFrom.HasValue)

                    query = query.Where(c => createdDateFrom.Value <= c.CreatedDate);

                if (createdDateTo.HasValue)

                    query = query.Where(c => createdDateTo.Value >= c.CreatedDate);

                if (!string.IsNullOrWhiteSpace(email))

                    query = query.Where(c => c.Email.Contains(email));

                if (!string.IsNullOrWhiteSpace(username))

                    query = query.Where(c => c.Username.Contains(username));

                if (!string.IsNullOrWhiteSpace(phone))

                    query = query.Where(c => c.Phone.Contains(phone));

                query = query.OrderByDescending(c => c.CreatedDate);

                return query;

            }, pageIndex, pageSize, getOnlyTotalCount);

            return customers;

        }

        #endregion

2 Framework.Models.BaseSearchModel

namespace Framework.Models

{

    /// <summary>

    /// 【基本查询模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     当指定模型纪录实例需要通过指定查询操作后(默认获取模型纪录的所有实例,即不查询),在页面Jquery DataTabes插件渲染(显示)出来,则通过该类及其属性成员实例实现这些操作。

    ///  注意:

    ///     该纪录是抽象纪录,所以该纪录只能被其它纪录所继承,并由继承纪录所实例化。

    /// </remarks>

    /// </summary>

    public abstract record BaseSearchModel

    {

        #region  拷贝构造方法

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

        ///     实例化该纪录时,该纪录实例默认设置了Jquery DataTabes插件每页最多显示行数为:10行。

        /// </remarks>

        /// </summary

        public BaseSearchModel()

        {

            Length = 10;

        }

        #endregion

        #region 属性

        /// <summary>

        /// 【页数】

        /// <remarks>

        /// 摘要:

        ///     获取Jquery DataTable插件的当前页(Jquery DataTable插件默认开始页为:0;而该属性实例则把该默认开始页设置为:1,如果使用默认Jquery DataTable插件,则插件最后页会现没有匹配结果异常,即Jquery DataTable插件会多出1)

        /// </remarks>

        /// </summary>

        public long Page => (Start / Length) + 1;

        /// <summary>

        /// 【页面大小】

        /// <remarks>

        /// 摘要:

        ///     获取Jquery DataTable插件每页最多的行数值:10行。  

        /// 注意:

        ///     该属性为只读属性,该属性的实例值由该类中“Length”属性成员所决定。

        /// </remarks>

        /// </summary>

        public int PageSize => Length;

        /// <summary>

        /// 【绘制】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定的Jquery DataTable插件被操作的次数值。

        /// </remarks>

        /// </summary>

        public string Draw { get; set; }

        /// <summary>

        /// 【开始】

        /// <remarks>

        /// 摘要:

        ///     获取/设置Jquery DataTable插件当前显示页面,需要跳过的行数值:=(页数-1)*PageSize(Length10Start>=0)。  

        /// </remarks>

        /// </summary>

        public long Start { get; set; }

        /// <summary>

        /// 【长度】

        /// <remarks>

        /// 摘要:

        ///     获取/设置Jquery DataTable插件每页最多的行数值:10Length>=1  

        /// </remarks>

        /// </summary>

        public int Length { get; set; }

        #endregion

    }

}

3 Framework.Models.BasePagedListModel<T>

namespace Framework.Models

{

    ///<typeparam name="T">泛型类型实例(1个指定类的类型实例)</typeparam>

    /// <summary>

    /// 【基本分页列表模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     该类及其属性成员实例,为Jquery DataTable插件渲染显示提供基本且必须的数据支撑。

    ///  注意:

    ///     该纪录是抽象纪录,所以该纪录只能被其它纪录所继承,并由继承纪录所实例化。

    /// </remarks>

    public abstract record BasePagedListModel<T>

    {

        #region 属性--Jquery DataTable插件

        /// <summary>

        /// 【数据】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个可枚举数实例,该实例存储着Jquery DataTable插件当前页渲染显示所需的数据。

        /// 注意:

        ///     因为Jquery DataTable插件是通过Jquery Ajax操作在浏览器中渲染出1指定类中的所有实例数据,所以该属性必须被命名为“Data”,也只能被命名为“Data”,否则浏览器中将不会渲染出这些数据。

        /// </remarks>

        /// </summary>

        public IEnumerable<T> Data { get; set; }

        /// <summary>

        /// 【绘制】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定的Jquery DataTable插件被操作的次数值。

        /// </remarks>

        /// </summary>

        public string Draw { get; set; }

        /// <summary>

        /// 【过滤总计】

        /// <remarks>

        /// 摘要:

        ///     获取/设置符合指定过滤条件的1个指定实体所有实例的总计值。

        /// </remarks>

        /// </summary>

        public long RecordsFiltered { get; set; }

        /// <summary>

        /// 【记录总计】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定实体所有实例的总计值。

        /// </remarks>

        /// </summary>

        public long RecordsTotal { get; set; }

        #endregion

    }

}

4 Framework.Models.Extensions.ModelExtensions

using Core;

using Framework.Models;

namespace Web.Framework.Models.Extensions

{

    /// <summary>

    /// 【模型扩展--类】

    /// <remarks>

    /// 摘要:

    ///     通过该类中的方法成员把实体实例中数据转换为JQuery DataTables控件分页渲染显示所需的数据。

    /// </remarks>

    public static class ModelExtensions

    {

        /// <typeparam name="TListModel">泛型类型实例(这里特指:分页列表模型类型实例,例如:CustomerListModel继承于BasePagedListModel)</typeparam>

        /// <typeparam name="TModel">泛型类型实例(这里特指:模型类型实例,例如:CustomerModel继承于BaseEntityModel)</typeparam>

        /// <typeparam name="TObject">泛型类型实例(这里特指:实体类型实例,例如:Customer)</typeparam>

        /// <param name="listModel">分页列表模型的1个指定实例。</param>

        /// <param name="searchModel">表单查询模型的1指定实例</param>

        /// <param name="objectList">(逻辑)分页列表实例,只逻辑的从数据源中加载指定1页中的数据,存储到“PagedList”类的实例中,从而以最少的数据量,提升页面的刷新渲染速度。</param>

        /// <param name="dataFillFunction">1个通过委托方法定义的查询条件实例。</param>

        /// <summary>

        /// 【预处理表格】

        /// <remarks>

        /// 摘要:

        ///   获取数据源中符合指定查询条件的所有实例后,把这些实例存储到“IEnumerable”(可枚举/枚举数)接口实例中。

        /// </remarks>

        /// <returns>

        ///    “IEnumerable”(可枚举/枚举数)接口实例。

        /// </returns>

        public static TListModel PrepareToGrid<TListModel, TModel, TObject>(this TListModel listModel,

            BaseSearchModel searchModel, IPagedList<TObject> objectList, Func<IEnumerable<TModel>> dataFillFunction)

            where TListModel : BasePagedListModel<TModel>

        {

            if (listModel == null)

                throw new ArgumentNullException(nameof(listModel));

            listModel.Data = dataFillFunction?.Invoke();

            listModel.Draw = searchModel?.Draw;

            listModel.RecordsTotal = objectList?.TotalCount ?? 0;

            listModel.RecordsFiltered = objectList?.TotalCount ?? 0;

            return listModel;

        }

        /// <typeparam name="TListModel">泛型类型实例(这里特指:分页列表模型类型实例,例如:CustomerListModel继承于BasePagedListModel)</typeparam>

        /// <typeparam name="TModel">泛型类型实例(这里特指:模型类型实例,例如:CustomerModel继承于BaseEntityModel)</typeparam>

        /// <typeparam name="TObject">泛型类型实例(这里特指:实体类型实例,例如:Customer)</typeparam>

        /// <param name="listModel">分页列表模型的1个指定实例。</param>

        /// <param name="searchModel">表单查询模型的1指定实例</param>

        /// <param name="objectList">(逻辑)分页列表实例,只逻辑的从数据源中加载指定1页中的数据,存储到“PagedList”类的实例中,从而以最少的数据量,提升页面的刷新渲染速度。</param>

        /// <param name="dataFillFunction">1个通过(阻塞性:ValueTask)异步委托方法定义的查询条件实例。</param>

        /// <summary>

        /// 【异步预处理表格】

        /// <remarks>

        /// 摘要:

        ///    以异步操作方式,获取数据源中符合指定查询条件的所有实例后,把这些实例存储到“IAsyncEnumerable”(可枚举/枚举数)接口实例中。

        /// </remarks>

        /// <returns>

        ///    “IAsyncEnumerable”(可枚举/枚举数)接口实例。

        /// </returns>

        public static async Task<TListModel> PrepareToGridAsync<TListModel, TModel, TObject>(this TListModel listModel,

            BaseSearchModel searchModel, IPagedList<TObject> objectList, Func<IAsyncEnumerable<TModel>> dataFillFunction)

            where TListModel : BasePagedListModel<TModel>

        {

            if (listModel == null)

                throw new ArgumentNullException(nameof(listModel));

            //ToListAsync()Core->Nuget->System.Linq.Async

            listModel.Data = await (dataFillFunction?.Invoke()).ToListAsync();

            listModel.Draw = searchModel?.Draw;

            listModel.RecordsTotal = objectList?.TotalCount ?? 0;

            listModel.RecordsFiltered = objectList?.TotalCount ?? 0;

            return listModel;

        }

    }

}

5 Web.Areas.Admin.Models.Customers.CustomerSearchModel

using Framework.Models;

namespace Web.Areas.Admin.Models.Customers

{

    /// <summary>

    /// 【用户过滤筛选模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     为用户表的过滤筛选操作提供数据支撑后,把这些数据对JQuery DataTables插件表格进行渲染显示。

    /// </remarks>

    /// </summary>

    public record CustomerSearchModel : BaseSearchModel

    {

        #region 拷贝构造方法

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

        ///     实例化该纪录时,为列表接口类型的属性成员实例分配内存空间。

        /// </remarks>

        /// </summary

        public CustomerSearchModel()

        {

        }

        #endregion

        #region 属性

        #endregion

    }

}

6 Web.Areas.Admin.Models.Customers.CustomerModel

using Framework.Models;

namespace Web.Areas.Admin.Models.Customers

{

    /// <summary>

    /// 【用户模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     为用户JQuery DataTables表格、添加和编辑Razor页面输入和验证的渲染显示提供数据支撑。

    /// </remarks>

    /// </summary>

    public record CustomerModel : BaseEntityModel

    {

        /// <summary>

        /// 【用户名】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定的用户名(账户、昵称)

        /// </remarks>

        /// </summary>

        public string Username { get; set; }

        /// <summary>

        /// 【电子邮箱】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户所对应的电子邮箱。

        /// </remarks>

        /// </summary>

        public string Email { get; set; }

        /// <summary>

        /// 【身份证号】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户所对应的身份证号。

        /// </remarks>

        /// </summary>

        //public string IdCard { get; set; }

        /// <summary>

        /// 【实名】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户所对应的实名。

        /// </remarks>

        /// </summary>

        //public string RealName { get; set; }

        /// <summary>

        /// 【密码】

        /// <remarks>

        /// 摘要:

        ///    获取/设置经过指定加密方式加密后的密码字符串。

        /// </remarks>

        /// </summary>

        public string Password { get; set; }

        /*

        可逆加密(Encryption)方式和哈希(Hash)加密方式的区别:

           1、可逆加密(Encryption)是可逆的,即明码和加密码之间通过操作是可以相互转换;哈希(Hash)加密方式是不可逆的,哈希(Hash)加密方式一般会导致信息熵减小,即使用哈希(Hash)加密方式转换后可能导致,转换明码是原明码中的一段。

           2、可逆加密(Encryption)的密码会随着明码的长度进行改变;而哈希(Hash)加密方式密码的长度是固定的,且只取决于所使用的算法,当明码的长度大于算法中所规则的长度时,哈希(Hash)加密方式会把明码截断后进行加密操作,这也是导致哈希(Hash)加密方式不可逆的与信息熵减小的根本原因。

           3、应用场景:一般情况下用户密码加密操作使用可逆加密(Encryption)方式;哈希(Hash)加密方式(一般用于数字签名、数据校验(CRCSHAMD5),据说HTTPS协议运行所需要的CA证书就是使用哈希(Hash)算法生成的。

           4、哈希(Hash)加密方式无解密操作,即哈希(Hash)加密方式是不能被解密的,如果用户输入的密码经过哈希(Hash)加密方式加密后的加密字符串与原加密字符相等,则用户通过验证,可以登录了。

        */

        /// <summary>

        /// 【哈希密钥】

        /// <remarks>

        /// 摘要:

        ///     获取/设置哈希(Hash)加密方式所需的密钥字符串(默认:5个字符的字符串)

        ///  说明:

        ///     使用哈希加密方式对用户的密进行加密操作时,所使用的密钥字符串。

        /// </remarks>

        /// </summary>

        public string PasswordSalt { get; set; }

        /// <summary>

        /// 【性别】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户所对应的性别。

        /// </remarks>

        /// </summary>

       // public int Gender { get; set; }

        /// <summary>

        /// 【手机号】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户所对应的手机号。

        /// </remarks>

        /// </summary>

        public string Phone { get; set; }

        /// <summary>

        /// 【头像】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户所对应的头像图片网络格式的路径字符串。

        ///  说明:

        ///     1、本地为网络格式的相对路径字符串。

        ///     2、第3方云端为网络格式的绝对路径字符串。

        /// </remarks>

        /// </summary>

        public string Avatar { get; set; }

        /// <summary>

        /// 【登录失败次数】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户执行同1次登录操作时密码输入错误的次数。

        /// 说明:

        ///     用于纪录密码输入错误的次数,在用户输入的密码错误次数超过限定值时,设定1个指定的时间值,在该时间值内,用户将用法执行登录操作(通过直接重定向到登出操作)

        /// </remarks>

        /// </summary>

       // public int FailedLoginAttempts { get; set; }

        /// <summary>

        /// 【可用?】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个值false(默认值:禁用)/true(可用),该值指示用户实体的1个指定实例是否处于可用状态。

        /// </remarks>

        /// </summary>

        public bool Active { get; set; }

        /// <summary>

        /// (辑删除?】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个值false(可用)/true(已经被逻辑删除),该值指示用户实体的1个指定实例是否已经处于逻辑删除状态。

        /// </remarks>

        /// </summary>

        public bool Deleted { get; set; }

        /// <summary>

        /// 【系统帐户?】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个值false(默认值:不是)/true(),该值指示用户实体的1个指定实例是否是系统帐户。

        /// 说明:

        ///     如果是系统帐户,则该用户将不能被物理/逻辑删除,即在删除操作中会通过该属性实例过滤掉系统帐户的所有用户。

        /// </remarks>

        /// </summary>

        public bool IsSystemAccount { get; set; }

        /// <summary>

        /// 【最后IP地址】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户最后1次执行登录操作的IP地址。

        /// </remarks>

        /// </summary>

       // public string LastIpAddress { get; set; }

        /// <summary>

        /// 【生日】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户的生日。

        /// </remarks>

        /// </summary>

        //public DateTime? DateOfBirth { get; set; }

        /// <summary>

        /// 【最后登录时间】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户最后1次执行登录操作的时间。

        /// </remarks>

        /// </summary>

        //public DateTime? LastLoginDate { get; set; }

        /// <summary>

        /// 【最后活动时间】

        /// <remarks>

        /// 摘要:

        ///     获取/设置用户实体1个指定实例最后一次操作的时间。

        /// 说明:

        ///     在默认情况下每间隔20分钟,如果已经登录的用户有操作则对用户实体1个指定实例最后一次操作的时间进行更新。

        /// </remarks>

        /// </summary>

        //public DateTime LastActivityDate { get; set; }

        /// <summary>

        /// 【无法登录时间】

        /// <remarks>

        /// 摘要:

        ///     获取/设置1个指定用户无法登录的时间。

        /// 说明:

        ///     在用户输入的密码错误次数超过限定值时,设定1个指定的时间值,在该时间值内,用户将用法执行登录操作(通过直接重定向到登出操作)

        /// </remarks>

        /// </summary>

        //public DateTime? CannotLoginUntilDate { get; set; }

        /// <summary>

        /// 【创建时间】

        /// <remarks>

        /// 摘要:

        ///     获取/设置用户实体1个指定实例第1次被持久化到用户表中的时间。

        /// </remarks>

        /// </summary>

        public DateTime CreatedDate { get; set; }

    }

}

7 Web.Areas.Admin.Models.Customers.CustomerListModel

using Framework.Models;

namespace Web.Areas.Admin.Models.Customers

{

    /// <summary>

    /// 【用户分页列表模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     该纪录没有定义任何成员实现,它的作用只是能够通过该纪录能够对抽象基纪录进行实例化,为Jquery DataTable插件当前页渲染显示提供基本且必须的数据支撑。

    /// </remarks>

    public record CustomerListModel : BasePagedListModel<CustomerModel>

    {

    }

}

8 Web.Areas.Admin.Infrastructure.Mapper.AdminMapperConfiguration.CreateCustomersMaps

 /// <summary>

        /// 【新建用户配置映射】

        /// <remarks>

        /// 摘要:

        ///     该方法用于与用户相关的两个实例之间的赋值操作定义进行集中管理。

        /// </remarks>

        /// </summary>

        protected virtual void CreateCustomersMaps()

        {

            CreateMap<Role, RoleModel>();

            CreateMap<RoleModel, Role>();

            CreateMap<Customer, CustomerModel>();

            CreateMap<CustomerModel, Customer>();

        }

9 Web.Areas.Admin.Factories.ICustomerModelFactory

using Web.Areas.Admin.Models.Customers;

namespace Web.Areas.Admin.Factories

{

    /// <summary>

    /// 【用户模型工厂--接口】

    /// <remarks>

    /// 摘要:

    ///     通过继承于该接口具体实现类中的方法成员,为用户控制器行方法成员提供预处理的数据支撑。

    /// </remarks>

    /// </summary>

    public interface ICustomerModelFactory

    {

        /// <param name="searchModel">用户过滤筛选模型纪录的1个指定实例。</param>

        /// <summary>

        /// 【异步预处理滤筛选模型纪录】

        /// <remarks>

        /// 摘要:

        ///     获取用户过滤筛选模型纪录的1个指定实例,为用户查询表单的渲染显示提供数据支撑。

        /// </remarks>

        /// <returns>

        ///    用户过滤筛选模型纪录的1个指定实例。

        /// </returns>

        /// </summary>

        Task<CustomerSearchModel> PrepareCustomerSearchModelAsync(CustomerSearchModel searchModel);

        /// <param name="searchModel">用户过滤筛选模型纪录的1个指定实例。</param>

        /// <summary>

        /// 【异步预处理用户分页列表模型纪录】

        /// <remarks>

        /// 摘要:

        ///     获取用户分页列表模型纪录的1个指定实例,为Jquery DataTable插件当前页渲染显示提供基本且必须的数据支撑。

        /// </remarks>

        /// <returns>

        ///      用户分页列表模型纪录的1个指定实例。

        /// </returns>

        /// </summary>

        Task<CustomerListModel> PrepareCustomerListModelAsync(CustomerSearchModel searchModel);

    }

}

10 Web.Areas.Admin.Factories.CustomerModelFactory

using Services.Customers;

using Web.Areas.Admin.Infrastructure.Mapper.Extensions;

using Web.Areas.Admin.Models.Customers;

using Web.Framework.Models.Extensions;

namespace Web.Areas.Admin.Factories

{

    /// <summary>

    /// 【用户模型工厂--类】

    /// <remarks>

    /// 摘要:

    ///     通过该类中的方法成员,为用户控制器行方法成员提供预处理的数据支撑。

    /// </remarks>

    /// </summary>

    public class CustomerModelFactory : ICustomerModelFactory

    {

        #region 拷贝构造方法与变量

        private readonly ICustomerService _customerService;

        /// <summary>

        /// 【拷贝构建方法】

        /// <remarks>

        /// 摘要:

        ///     依赖注入容器通过拷贝构造方法,实例化该类中的变量成员。

        /// </remarks>

        /// </summary>

        public CustomerModelFactory(ICustomerService customerService)

        {

            _customerService = customerService;

        }

        #endregion

        /// <param name="searchModel">用户过滤筛选模型纪录的1个指定实例。</param>

        /// <summary>

        /// 【异步预处理滤筛选模型纪录】

        /// <remarks>

        /// 摘要:

        ///     获取用户过滤筛选模型纪录的1个指定实例,为用户查询表单的渲染显示提供数据支撑。

        /// </remarks>

        /// <returns>

        ///    用户过滤筛选模型纪录的1个指定实例。

        /// </returns>

        /// </summary>

        public virtual async Task<CustomerSearchModel> PrepareCustomerSearchModelAsync(CustomerSearchModel searchModel)

        {

            if (searchModel == null)

                throw new ArgumentNullException(nameof(searchModel));

            return searchModel;

        }

        /// <param name="searchModel">用户过滤筛选模型纪录的1个指定实例。</param>

        /// <summary>

        /// 【异步预处理用户分页列表模型纪录】

        /// <remarks>

        /// 摘要:

        ///     获取用户分页列表模型纪录的1个指定实例,为Jquery DataTable插件当前页渲染显示提供基本且必须的数据支撑。

        /// </remarks>

        /// <returns>

        ///      用户分页列表模型纪录的1个指定实例。

        /// </returns>

        /// </summary>

        public virtual async Task<CustomerListModel> PrepareCustomerListModelAsync(CustomerSearchModel searchModel)

        {

            //根据前端传递的用户过滤筛选模型纪录的1个指定实例,从用户表中获取(1逻辑页中的)相应行数的数据,并把这些数据存储到列表实例中。

            var customers = await _customerService.GetAllCustomersAsync(pageIndex: searchModel.Page - 1, pageSize: searchModel.PageSize);

            //实例化当前用户分页列表模型纪录(“物理页”),为Jquery DataTable插件当前页渲染显示提供基本且必须的数据支撑。

            var model = new CustomerListModel().PrepareToGrid(searchModel, customers, () =>

            {

                return customers.Select(customer =>

                {

                    var customerModel = customer.ToModel<CustomerModel>();

                    return customerModel;

                }).ToList();

            });

            return model;

        }

    }

}

11 Web.Infrastructure.DIStartup

using Web.Areas.Admin.Factories;

namespace Web.Infrastructure

{

    public class DIStartup : Core.Infrastructure.IStartup

    {

        #region 属性--接口实现

        /// <summary>

        /// 【顺序】

        /// <remarks>

        /// 摘要:

        ///     获取依赖注入启动类中管道中间件实例,被集成到内置管道实例中的顺序,默认值:2000

        /// 注意:

        ///     .NetCore框架默定义了一些常用的内置管道中间件,并默认规定了这些内置管道中间件实例在内置管道实例中被调用的顺序,

        /// 如果不按照该默认顺序调用这些内置管道中间件,在程序执行时就会出现逻辑异常。

        /// </remarks>

        /// </summary>

        public int Order => 2002;

        #endregion

        #region 方法--接口实现

        /// <param name="services">.Net(Core)框架内置依赖注入容器实例。</param>

        /// <param name="configuration">.NetCore框架内置配置接口实例(存储着当前程序中所有*.json文件中的数据)</param>

        /// <summary>

        /// 【配置服务】

        /// <remarks>

        /// 摘要:

        ///     通过该方法成员,对当前程序中的依赖注入定义操作进行集中管理。

        /// </remarks>

        /// </summary>

        public virtual void ConfigureServices(IServiceCollection services, IConfiguration configuration)

        {

            services.AddScoped<ICustomerModelFactory, CustomerModelFactory>();

        }

        /// <param name="application">.NetCore框架内置管道接口实例。</param>

        /// <summary>

        /// 【配置】

        /// <remarks>

        /// 摘要:

        ///     依赖注入功能不参与程序与页面的/操作,所有该方法成员中没有管道中间件集成到内置管道中间件的任何定义。

        /// </remarks>

        /// </summary>

        public void Configure(IApplicationBuilder application)

        {

        }

        #endregion

    }

}

12 Web.Areas.Admin.Controllers.CustomerController

using Microsoft.AspNetCore.Mvc;

using Web.Areas.Admin.Factories;

using Web.Areas.Admin.Models.Customers;

namespace Web.Areas.Admin.Controllers

{

    [Area("Admin")]

    public class CustomerController : Controller

    {

        #region 拷贝构造方法与变量

        private readonly ICustomerModelFactory _customerModelFactory;

        /// <summary>

        /// 【拷贝构建方法】

        /// <remarks>

        /// 摘要:

        ///     依赖注入容器通过拷贝构造方法,实例化该类中的变量成员。

        /// </remarks>

        /// </summary>

        public CustomerController(ICustomerModelFactory customerModelFactory)

        {

            _customerModelFactory = customerModelFactory;

        }

        #endregion

        #region CURD

        /// <summary>

        /// 【用户索引】

        /// <remarks>

        /// 摘要:

        ///    初始化用户过滤筛选模型纪录的1个指定实例,为用户查询表单的渲染显示提供数据支撑。

        /// </remarks>

        /// <returns>

        ///    用户查询表单的渲染显示。

        /// </returns>

        /// </summary>

        public virtual async Task<IActionResult> Index()

        {

            var model = await _customerModelFactory.PrepareCustomerSearchModelAsync(new CustomerSearchModel());

            return View(model);

        }

        /// <param name="searchModel">用户过滤筛选模型纪录的1个指定实例。</param>

        /// <summary>

        /// 【用户列表】

        /// <remarks>

        /// 摘要:

        ///    把用户分页列表模型纪录的1个指定实例,转换为JSON编码格式的数据,为Jquery DataTable插件当前页渲染显示提供基本且必须的数据支撑。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     JSON编码格式的数据,为Jquery DataTable插件当前页渲染显示提供基本且必须的数据支撑。

        /// </returns>

        /// </summary>

        [HttpPost]

        public virtual async Task<IActionResult> CustomerList(CustomerSearchModel searchModel)

        {

            var model = await _customerModelFactory.PrepareCustomerListModelAsync(searchModel);

            return Json(model);

        }

        #endregion

    }

}

230525_017ShopRazor(分页与JQuery DataTables渲染显示)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值