• 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:

     

     

  • 相关阅读:
    解决跨操作系统平台JSON中文乱码问题
    httpencode编码
    DELPHI搭建centos开发环境
    cross socket和msgpack的数据序列和还原
    libmidas.so.2
    开发WINDOWS服务程序
    idhttp访问DATASNAP有密码验证的中间件
    接口操作XML
    HttpApplication中的异步线程
    Assembly类
  • 原文地址:https://www.cnblogs.com/liuyang95/p/13245921.html
Copyright © 2020-2023  润新知