1 翻页
Query String http://localhost:5000/api/posts?pageIndex=2&pageSize=10&orderBy=Id
1.1数据分页
1.建立 QueryParameters.cs 数据分页方法类 包含.pageIndex, pageSize, orderBy 等分页参数
2.建立PostParameters.cs post专用的分页类,继承自QueryParameters.cs 即可.(无特殊条件可以不用写其他内容,继承功能够用即可)
3.1把PostParameters 传给PostController.cs 的[HttpGet] 如下:
public async Task<IActionResult> Get(PostParameters postParameters)
3.2把postParameters传给PostController.cs具体的实现方法
原来:
var postList = await _postRepository.GetAllPostAsync();
改为:
var postList = await _postRepository.GetAllPostAsync(postParameters);
3.3给接口添加参数
同时修改接口
原来:
Task<PaginatedList<Post>> GetAllPostAsync();
改为:
Task<PaginatedList<Post>> GetAllPostAsync(PostParameters postParameters);
3.4在实现类添加参数 PostParameters postParameters,同时原来的列表方法修改下如下
原来为直接列出列表数据.
return await _myContext.Post.ToListAsync();
改为:
1.按Id排序
var query = _myContext.Post.OrderBy(x => x.Id);
2.数据分页
var data = await query.Skip(postParameters.PageIndex * postParameters.PageSize)
.Take(postParameters.PageSize).ToListAsync();
1.2分页按钮(不含上一页 下一页) ,定义一个PageList.cs 记录 翻页数据
public class PaginatedList<T> : List<T> where T : class { public int PageSize { get; set; } public int PageIndex { get; set; } private int _totalItemsCount; public int TotalItemsCount { get => _totalItemsCount; set => _totalItemsCount = value >= 0 ? value : 0; } public int PageCount => TotalItemsCount / PageSize + (TotalItemsCount % PageSize > 0 ? 1 : 0); public bool HasPrevious => PageIndex > 0; public bool HasNext => PageIndex < PageCount - 1; public PaginatedList(int pageIndex, int pageSize, int totalItemsCount, IEnumerable<T> data) { PageIndex = pageIndex; PageSize = pageSize; TotalItemsCount = totalItemsCount; AddRange(data); } }
修改PostRepository.cs
原返回类型: public async Task<IEnumerable<Post>> GetAllPostAsync(PostParameters postParameters) 修改为: public async Task<PaginatedList<Post>> GetAllPostAsync(PostParameters postParameters)
同时修改对应的接口的返回类型.
再修改PostRepository.cs 具体的代码
1.统计出总条数
var count = await query.CountAsync();
2.把原来的返回数据返回给一个变量如 var data
var data = await query.Skip(postParameters.PageIndex * postParameters.PageSize)
.Take(postParameters.PageSize).ToListAsync();
3.以上信息组合成返回数据
return new PaginatedList<Post>(postParameters.PageIndex,postParameters.PageSize,count,data);
4.在PostController创建匿名类 ,并将属性名改成首字母小写.(new部分负责)
var meta = new { Pagesize = postList.PageSize, Pageindex = postList.PageIndex, TotalItemsCount = postList.TotalItemsCount, PageCount = postList.PageCount }; Response.Headers.Add("x-Pagination",JsonConvert.SerializeObject(meta,new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }));
1.3分页 上一页 下一页
使用IUrlHelper 用之前需要配置 IActionContextAccessor 这个东西,在Controller里写一个自定义的方法返回前一页 后一页.
1.创建一个枚举类PaginationResourceUriType.cs
namespace BlogDemo.Core.Entities { public enum PaginationResourceUriType { CurrentPage, PreviousPage, NextPage } }
2.startup注册IUrlHelper
//注册UrlHelper services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); services.AddScoped<IUrlHelper>(factory => { var actionContext = factory.GetService<IActionContextAccessor>().ActionContext; return new UrlHelper(actionContext); });
3.在PostController里添加一个创建Url的方法
private string CreatePostUri(PostParameters parameters, PaginationResourceUriType uriType) { switch (uriType) { case PaginationResourceUriType.PreviousPage: var previousParameters = new { pageIndex = parameters.PageIndex - 1, pageSize = parameters.PageSize, orderBy = parameters.OrderBy, fields = parameters.Fields }; return _urlHelper.Link("GetPosts", previousParameters); case PaginationResourceUriType.NextPage: var nextParameters = new { pageIndex = parameters.PageIndex + 1, pageSize = parameters.PageSize, orderBy = parameters.OrderBy, fields = parameters.Fields }; return _urlHelper.Link("GetPosts", nextParameters); default: var currentParameters = new { pageIndex = parameters.PageIndex, pageSize = parameters.PageSize, orderBy = parameters.OrderBy, fields = parameters.Fields }; return _urlHelper.Link("GetPosts", currentParameters); } }
给[HttpGet]起个名字 [HttpGet(Name = "GetPosts")] 针对这个名字的 Get操作
4.在匿名类上生成前一页后一页连接,并将生成的 previousPageLink nextPageLink添加到元数据.
var previousPageLink = postList.HasPrevious ? CreatePostUri(postParameters, PaginationResourceUriType.PreviousPage) : null; var nextPageLink = postList.HasNext ? CreatePostUri(postParameters, PaginationResourceUriType.NextPage) : null;
调试查看结果
2.过滤 条件应用于Resource Model.
过滤: 对集合资源附加一些条件, 筛选出结果.如: http://localhost:5000/api/countries?englishName=China.
过滤属性可以放在QueryParameters的子类里.
搜索: 使用关键字对集合资源进行模糊搜索.
http://localhost/api/countries?searchTerm=hin
2.1 在PostParameters增加一个Title属性.(Post实体里有)
public string Title { get; set; }
2.2 然后在PostRepository进行过滤
原来: var query = _myContext.Post.OrderBy(x => x.Id);
修改:将query先出集合数据,再排序.中间加上条件判断.
var query = _myContext.Post.AsQueryable(); if (!string.IsNullOrEmpty(postParameters.Title)) { var title = postParameters.Title.ToLowerInvariant(); query = query.Where(x => x.Title.ToLowerInvariant().Contains(title)); } query=query.OrderBy(x => x.Id);
执行调试 如:https://localhost:5001/api/posts?pageindex=0&pagesize=3&title=Post Title 4
3.排序 在Infrastructure里安装System.Linq.Dynamic.Core
排序思路:建立三层的服务.
第一层 容器层:PropertyMappingContainer
PostResource 到 Post他两之间属性有一些映射,我们把它两之间的属性映射算成一对,注册到这个容器.
第二层:他两之间的属性映射PropertyMapping(PostPropertyMapping)
第三次:具体到每个映射的属性MappedProperty
Services文件夹下的cs文件解析,常规的,不需要改变,项目组复制使用即可.
1.1.MappedProperty.cs Resource和Entity 要求字段要对应:名字(Name) , //排序是否是相反的(Revert).
public class MappedProperty { public string Name { get; set; } public bool Revert { get; set; } }
1.2 PropertyMapping.cs 两个表之间的映射关系.
Resources/PostPropertyMapping.cs 继承PropertyMapping.cs 且实现两表之间的具体映射.
public class PostPropertyMapping : PropertyMapping<PostResource, Post> { public PostPropertyMapping() : base( new Dictionary<string, List<MappedProperty>> (StringComparer.OrdinalIgnoreCase) { [nameof(PostResource.Title)] = new List<MappedProperty> { new MappedProperty{ Name = nameof(Post.Title), Revert = false} }, [nameof(PostResource.Body)] = new List<MappedProperty> { new MappedProperty{ Name = nameof(Post.Body), Revert = false} }, [nameof(PostResource.Author)] = new List<MappedProperty> { new MappedProperty{ Name = nameof(Post.Author), Revert = false} } }) { } }
1.3使用容器
1.4startup注册
1.5使用排序,在Infrastructure项目建立 Extensions/QueryableExtensions.cs类.
1.6在PostRepository添加 IPropertyMappingContainer构造函数.再修改如下注释的代码
//query = query.OrderBy(x => x.Id); query = query.ApplySort(postParameters.OrderBy, _propertyMappingContainer.Resolve<PostResource, Post>());