翻页、过滤
通过api可能要获取某页的数据,也可能获取后一页,或者前一页的数据,所以就需要实现翻页处理。
增加类处理参数
public abstract class QueryParameter : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private const int defaultPageSize = 10;
private const int defaultMaxPageSize = 100;
private int _pageIndex;
public int PageIndex
{
get { return _pageIndex; }
set { _pageIndex = value > 0 ? value : 0; }
}
public int _pageSize = defaultPageSize;
public int PageSize
{
get { return _pageSize; }
set { _pageSize = value; }
}
private string _orderBy;
public string OrderBy
{
get { return _orderBy; }
set { _orderBy = value ?? nameof(IEntity.Id); }
}
private int _maxPageSize = defaultMaxPageSize;
protected internal virtual int MaxPageSize
{
get { return _maxPageSize; }
set { _maxPageSize = value; }
}
public string Fields
{
get;set;
}
protected void onPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
其中INotifyPropertyChanged
接口是为了实现能够实时绑定显示的。
这个类中主要定义了PageIndex、PageSize、MaxPageSize
几个主要用于显示的参数。
然后实体POST
继承这个类,也就继承了这个参数。
在接口中传递参数类
Task<PaginatedList<Post>> GetAllPosts(PostParamters postParamters);
在控制器中使用参数后
public async Task<IActionResult> Get(PostParamters postParamters)
{
var postList = await _postRepository.GetAllPosts(postParamters);
}
Get方法会自动获取查询URL中传递的pageIndex/pagesize参数,自动解析成PostParameters的属性。
增加翻页处理
增加了一个枚举值,用于判断是当前页、前一页、后一页
public enum PaginationResourceUriType
{
CurrentPage,
PreviousPage,
NextPage
}
增加返回参数的处理。
如存在前一页,就返回pageIndex=currentPageIndex-1的处理。
private string CreatePostUri(PostParamters postParamters,PaginationResourceUriType paginationResourceUriType)
{
switch (paginationResourceUriType)
{
case PaginationResourceUriType.PreviousPage:
var previousParamters = new
{
pageIndex = postParamters.PageIndex - 1,
pageSize = postParamters.PageSize,
oderBy = postParamters.OrderBy,
fields = postParamters.Fields
};
//return _urlHelper.Link("GetPosts", previousParamters);
return Url.Link("GetPosts", previousParamters);
case PaginationResourceUriType.NextPage:
var nextParamters = new
{
pageIndex = postParamters.PageIndex + 1,
pageSize = postParamters.PageSize,
orderBy = postParamters.OrderBy,
fields = postParamters.Fields
};
//return _urlHelper.Link("GetPosts", nextParamters);
return Url.Link("GetPosts", nextParamters);
case PaginationResourceUriType.CurrentPage:
return _urlHelper.Link("GetPosts", postParamters);
default:
return "";
}
}
还有一个重要的类,就是对返回的数据处理,其中要包含有总共有多少数据,当前页有多少。
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 { return _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);
}
}
最终控制器中的代码如下:
[HttpGet(Name ="GetPosts")]
public async Task<IActionResult> Get(PostParamters postParamters)
{
var postList = await _postRepository.GetAllPosts(postParamters);
var postResource = _mapper.Map<IEnumerable<Post>, IEnumerable<PostResource>>(postList);
var previousPageLink = postList.HasPrevious ?
CreatePostUri(postParamters, PaginationResourceUriType.PreviousPage) : null;
var nextPageLink = postList.HasNext ?
CreatePostUri(postParamters, PaginationResourceUriType.NextPage) : null;
var meta = new {
PageSize = postList.PageSize,
PageIndex = postList.PageIndex,
TotalItemsCount = postList.TotalItemsCount,
PageCount = postList.PageCount,
previousPageLink,
nextPageLink
};
Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(meta));
return Ok(postResource);
}
返回的结果:
过滤
public async Task<PaginatedList<Post>> GetAllPosts(PostParamters postParamters)
{
var query = _myContext.Post.AsQueryable();
if(!string.IsNullOrEmpty(postParamters.Title))
{
var title = postParamters.Title;
query = query.Where(x => x.Title.Contains(title));
}
query = query.OrderBy(x => x.Id);
var count = await query.CountAsync();
var data=await query
.Skip(postParamters.PageIndex * postParamters.PageSize)
.Take(postParamters.PageSize)
.ToListAsync();
return new PaginatedList<Post>(postParamters.PageIndex, postParamters.PageSize, count, data);
}