net core RESTful Api笔记⑥

分页

针对集合资源的翻页

1.集合资源数量通常比较大,需要对他们进行翻页查询

2.避免性能问题

3.参数通过querystring进行传递:api/companies?pageNumber=1&pageSize=5

4.每一页书需要进行控制

5.默认应该进行分页

6.应该对底层数据存储进行分页

 因为之前对查询,更新,添加的model分开写了,所以这里只需要修改查询的dto就行了,又因为这是多个查询所以修改

CompanyDtoParameters:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Rountine.API.DtoParameters
{
    /// <summary>
    /// 复杂的查询条件
    /// </summary>
    public class CompanyDtoParameters
    {
        public string CompanyName { get; set; }

        public string searchTerm { get; set; }
        //默认1
        public int PageNumber { get; set; } = 1;
        //默认5
        public int PageSize { get; set; } = 5;

    }
}

修改CompanyRepository:添加了分页,删除之前两个判断冗余的查询

  public async Task<IEnumerable<Company>> GetCompaniesAsync(CompanyDtoParameters parameters)
        {
            if (parameters == null) 
            {
                throw new ArgumentException(nameof(parameters));
            }
           
            var queryExpression = _context.companies as IQueryable<Company>;
            if (!string.IsNullOrEmpty(parameters.CompanyName)) 
            {
                parameters.CompanyName = parameters.CompanyName.Trim();
                queryExpression = queryExpression.Where(x => parameters.CompanyName == x.Name);
            }
            if (!string.IsNullOrEmpty(parameters.searchTerm)) 
            {
                parameters.searchTerm = parameters.searchTerm.Trim();
                queryExpression = queryExpression.Where(x => x.introduction.Contains(parameters.searchTerm)
                                                         || x.Name.Contains(parameters.searchTerm));
            }
            queryExpression = queryExpression.Skip(parameters.PageSize * (parameters.PageNumber - 1)).Take(parameters.PageSize);
            return await queryExpression.ToListAsync();
        }

postman:

 

 返回翻页的信息

1.包含前一页和后一页的连接

2.其他信息:pageNumber,pagesize,总数,总页数

翻页信息

{
  "items":[{company},{company}...],
  "pagination":{"pageNumber":1,"pageSize":5,...}    
}

响应的body不符合请求的accept header,这不是application/json,他应该是一个新的media type

破坏了restful约束,api消费者不知道如何使用application/json这个media type

当时用application/json请求的时候,翻页信息不应该放到body里,应该有自定一的header里:x-pagination

实现自定义类:PagedList<T>:属性:CurrentPage,TotalPages,HasPrevious,HasNext

可以复用,在使用它创建翻页信息

添加pageList:里面都是分页的信息

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;

namespace Rountine.API.Helpers
{
    public class PageList<T>:List<T>
    {
        public int CurrentPage { get; private set; }
        public int ToTalPages { get; private set; }
        public int PageSize { get; private set; }
        public int ToTalCount{ get; private set; }
        public Boolean HasPrevious => CurrentPage > 1;
        public Boolean HasNext => CurrentPage < ToTalPages;
        public PageList(List<T>items,int count,int pageNumber,int pageSize)
        {
            ToTalCount = count;
            PageSize = pageSize;
            CurrentPage = pageNumber;
            ToTalPages = (int)Math.Ceiling(count/(double)pageSize);
            AddRange(items);
        }

        public static  async Task<PageList<T>> CreatAsync(IQueryable<T>source,int pageNumber,int pageSize)
        {
            var count = await source.CountAsync();
            var items = await source.Skip((pageNumber - 1) + pageSize).Take(pageSize).ToListAsync();
            return new PageList<T>(items,count,pageNumber,pageSize);
        }
    }
}

CompanyDtoParameters:修改查询多个公司的载体model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Rountine.API.DtoParameters
{
    /// <summary>
    /// 复杂的查询条件
    /// </summary>
    public class CompanyDtoParameters
    {
        private const int MaxPageSize = 100;
        public string CompanyName { get; set; }

        public string searchTerm { get; set; }
        //默认1
        public int PageNumber { get; set; } = 1;
        //默认5
        public int PageSize { get; set; } = 5;
        

    }
}

CompainesController:修改了查询多个公司的api,UnsafeRelaxedJsonEscaping修正返回的链接里的&

  [HttpGet(Name =nameof(GetCompanies))]
        public async Task<ActionResult<IEnumerable<CompanyDto>>> GetCompanies([FromQuery] CompanyDtoParameters parameters)
        {
            var companies = await _companyRepository.GetCompaniesAsync(parameters);

            var previousPageLink = companies.HasPrevious ? CreateCompaniesResourceUri(parameters, ResourceUriType.PreviousPage) : null;
            var nextPageLink = companies.HasNext ? CreateCompaniesResourceUri(parameters, ResourceUriType.NextPage) : null;

            var paginationMetadate = new
            {
                  totalCount= companies.ToTalCount,
                  pageSize=companies.PageSize,
                  currentPage=companies.CurrentPage,
                  totalPages=companies.ToTalPages,
                  previousPageLink,
                  nextPageLink
            };
            Response.Headers.Add("X-Pagination", JsonSerializer.Serialize(paginationMetadate, new JsonSerializerOptions
            {
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            }) ) ;
            var companyDto = _mapper.Map<IEnumerable<CompanyDto>>(companies);
            
            return Ok(companyDto);
        }

CreateCompaniesResourceUri:ControllerBase使用Url.Link将前一页后一页的链接弄出来

        private string CreateCompaniesResourceUri(CompanyDtoParameters parmaters, ResourceUriType type) 
        {
            switch (type) 
            {
                case ResourceUriType.PreviousPage:
                    return Url.Link(nameof(GetCompanies), new
                    {
                        pageNumber = parmaters.PageNumber - 1,
                        pageSize= parmaters.PageSize,
                        companyName= parmaters.CompanyName,
                        searchTerm= parmaters.searchTerm
                    });
                case ResourceUriType.NextPage:
                    return Url.Link(nameof(GetCompanies), new
                    {
                        pageNumber = parmaters.PageNumber + 1,
                        pageSize = parmaters.PageSize,
                        companyName = parmaters.CompanyName,
                        searchTerm = parmaters.searchTerm
                    });
                default:
                    return Url.Link(nameof(GetCompanies), new
                    {
                        pageNumber = parmaters.PageNumber,
                        pageSize = parmaters.PageSize,
                        companyName = parmaters.CompanyName,
                        searchTerm = parmaters.searchTerm
                    });
            }
        }

postman:

 

 

 

 

posted @ 2020-07-05 21:23  蔡老板2019  阅读(316)  评论(0编辑  收藏  举报