简体   繁体   English

如何使用 ASP.NET Core Web API 2.2 进行分页和过滤器

[英]How to make pagination and filters with ASP.NET Core Web API 2.2

I'm having problems to makes pagination and filters with ASP.NET Web API at version 2.2 do .NET Core.我在使用 ASP.NET Web API 在 2.2 版做 .NET Core 时遇到问题。

I tryed find a solution like the PagedList, but seems that not exists anything for ASP.NET Core.我试着找到一个像 PagedList 这样的解决方案,但似乎对于 ASP.NET Core 不存在任何东西。 So I started to implement some solution to my problem and her is like that:所以我开始对我的问题实施一些解决方案,她是这样的:

[HttpGet]
public async Task<IEnumerable<TripListViewModel>> GetTrips([FromQuery]TripsPaginationFilterViewModel model)
{
    var trips = await _viagemRepository.GetList(model.Page, model.Limit);

    return _mapper.Map<IEnumerable<TripListViewModel>>(trips);
}

public class TripsPaginationFilterViewModel : PaginationFilterViewModel
{
   public DateTime DateStart { get; set; }
   public DateTime DateFinish { get; set; }
   public Guid TrechoId { get; set; }
}

public class PaginationFilterViewModel
{
   public int Page { get; set; } = 1;
   public int Limit { get; set; } = 20;
   public bool IncludeInactivs { get; set; } = false;
}

public async Task<List<TEntity>> GetList(int page, int limit, Expression<Func<TEntity, bool>> predicate)
{
    if (predicate!= null)
    {
        return await DbSet.AsNoTracking().Where(predicate).Skip((page - 1) * limit).Take(limit).ToListAsync();
    }

    return await DbSet.AsNoTracking().Skip((page - 1) * limit).Take(limit).ToListAsync();
}

I would like to know how to tell the predicate as a parameter to the method of my repository filtering.我想知道如何将谓词作为参数告诉我的存储库过滤方法。

Copy and paste the following code into your project somewhere and you'll have access to a full IQueryable supported PagedListCollection.将以下代码复制并粘贴到您的项目中的某处,您将可以访问完整的 IQueryable 支持的 PagedListCollection。 Its taken from one of my projects.它取自我的一个项目。 It sits as extension methods to IQueryable and IEnumerable calls and allows you to do .ToPagedList() on your queries to return a paged collection它作为 IQueryable 和 IEnumerable 调用的扩展方法,并允许您对查询执行 .ToPagedList() 以返回分页集合

namespace Simple.Data.Pagination.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Interfaces;

    /// <summary>
    /// Provides some extension methods for <see cref="IEnumerable{T}" /> to provide paging capability.
    /// </summary>
    public static class EnumerablePagedListExtensions
    {
        /// <summary>
        /// Converts the specified source to <see cref="IPagedList{T}" /> by the specified <paramref name="pageIndex" /> and
        /// <paramref name="pageSize" />.
        /// </summary>
        /// <typeparam name="T">The type of the source.</typeparam>
        /// <param name="source">The source to paging.</param>
        /// <param name="pageIndex">The index of the page.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="indexFrom">The start index value.</param>
        /// <param name="totalCount">The Total Count</param>
        /// <returns>An instance of the inherited from <see cref="IPagedList{T}" /> interface.</returns>
        public static IPagedList<T> ToPagedList<T>(this IEnumerable<T> source, int pageIndex, int pageSize, int indexFrom = 0, int totalCount = 0) => new PagedList<T>(source, pageIndex, pageSize, totalCount);

        /// <summary>
        /// Converts the specified source to <see cref="IPagedList{T}" /> by the specified <paramref name="pageIndex" /> and
        /// <paramref name="pageSize" />.
        /// </summary>
        /// <typeparam name="T">The type of the source.</typeparam>
        /// <param name="source">The source to paging.</param>
        /// <param name="pageIndex">The index of the page.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="indexFrom">The start index value.</param>
        /// <returns>An instance of the inherited from <see cref="IPagedList{T}" /> interface.</returns>
        public static IPagedList<T> ToPagedList<T>(this IQueryable<T> source, int pageIndex, int pageSize, int indexFrom = 0) => new PagedList<T>(source, pageIndex, pageSize, indexFrom);

        /// <summary>
        /// Converts the specified source to <see cref="IPagedList{T}" /> by the specified <paramref name="converter" />,
        /// <paramref name="pageIndex" /> and <paramref name="pageSize" />
        /// </summary>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <typeparam name="TResult">The type of the result</typeparam>
        /// <param name="source">The source to convert.</param>
        /// <param name="converter">The converter to change the <typeparamref name="TSource" /> to <typeparamref name="TResult" />.</param>
        /// <param name="pageIndex">The page index.</param>
        /// <param name="pageSize">The page size.</param>
        /// <param name="indexFrom">The start index value.</param>
        /// <returns>An instance of the inherited from <see cref="IPagedList{T}" /> interface.</returns>
        public static IPagedList<TResult> ToPagedList<TSource, TResult>(this IEnumerable<TSource> source,
            Func<IEnumerable<TSource>, IEnumerable<TResult>> converter, int pageIndex, int pageSize,
            int indexFrom = 0) => new PagedList<TSource, TResult>(source, converter, pageIndex, pageSize, indexFrom);
    }
}


namespace Simple.Data.Pagination.Extensions
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using Interfaces;
    using Microsoft.EntityFrameworkCore;

    /// <summary>
    /// Extensions for the <see cref="IPagedList{T}"/>
    /// </summary>
    public static class QueryablePageListExtensions
    {
        /// <summary>
        /// Converts the specified source to <see cref="IPagedList{T}" /> by the specified <paramref name="pageIndex" /> and <paramref name="pageSize" />
        /// </summary>
        /// <typeparam name="T">The type of the source</typeparam>
        /// <param name="source">The source to paging</param>
        /// <param name="pageIndex">The index of the page</param>
        /// <param name="pageSize">The size of the page</param>
        /// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete</param>
        /// <param name="indexFrom">The start index value</param>
        /// <returns>An instance of the inherited from <see cref="IPagedList{T}"/> interface</returns>
        public static async Task<IPagedList<T>> ToPagedListAsync<T>(this IQueryable<T> source, int pageIndex, int pageSize, int indexFrom = 0, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (indexFrom > pageIndex)
            {
                throw new ArgumentException($"indexFrom: {indexFrom} > pageNumber: {pageIndex}, must indexFrom <= pageNumber");
            }

            var count = await source.CountAsync(cancellationToken).ConfigureAwait(false);
            var items = await source.Skip((pageIndex - indexFrom) * pageSize).Take(pageSize).ToListAsync(cancellationToken).ConfigureAwait(false);

            var pagedList = new PagedList<T>
            {
                PageNumber = pageIndex,
                PageSize = pageSize,
                IndexFrom = indexFrom,
                TotalCount = count,
                Items = items,
                TotalPages = (int)Math.Ceiling(count / (double)pageSize)
            };

            return pagedList;
        }
    }
}


namespace Simple.Data.Pagination.Interfaces
{
    using System.Collections.Generic;

    /// <summary>
    /// Provides the interface(s) for paged list of any type
    /// </summary>
    /// <typeparam name="T">The type for paging.</typeparam>
    public interface IPagedList<T>
    {
        /// <summary>
        /// Gets the Index Start Value
        /// </summary>
        int IndexFrom { get; }

        /// <summary>
        /// Gets the Page Number
        /// </summary>
        int PageNumber { get; }

        /// <summary>
        /// Gets the Page Size
        /// </summary>
        int PageSize { get; }

        /// <summary>
        /// Gets the Total Count of the list of <typeparamref name="T" />
        /// </summary>
        int TotalCount { get; }

        /// <summary>
        /// Gets the Total Pages
        /// </summary>
        int TotalPages { get; }

        /// <summary>
        /// Gets the Current Page Items
        /// </summary>
        IList<T> Items { get; }

        /// <summary>
        /// Gets a value indicating whether the paged list has a previous page
        /// </summary>
        bool HasPreviousPage { get; }

        /// <summary>
        /// Gets a value indicating whether the paged list has a next page
        /// </summary>
        bool HasNextPage { get; }
    }
}

namespace Simple.Data.Pagination
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Interfaces;

    /// <summary>
    /// Represents the default implementation of the <see cref="IPagedList{T}" /> interface
    /// </summary>
    /// <typeparam name="T">The type of the data to page</typeparam>
    public class PagedList<T> : IPagedList<T>
    {
        /// <inheritdoc />
        public int PageNumber { get; set; }

        /// <inheritdoc />
        public int PageSize { get; set; }

        /// <inheritdoc />
        public int TotalCount { get; set; }

        /// <inheritdoc />
        public int TotalPages { get; set; }

        /// <inheritdoc />
        public int IndexFrom { get; set; }

        /// <inheritdoc />
        public IList<T> Items { get; set; }

        /// <inheritdoc />
        public bool HasPreviousPage => this.PageNumber - this.IndexFrom > 0;

        /// <inheritdoc />
        public bool HasNextPage => this.PageNumber - this.IndexFrom + 1 < this.TotalPages;

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{T}" /> class.
        /// </summary>
        /// <param name="source">The Source Collection</param>
        /// <param name="pageNumber">The Page Number</param>
        /// <param name="pageSize">The Page Size</param>
        /// <param name="totalCount">The Total Item Count</param>
        public PagedList(IEnumerable<T> source, int pageNumber, int pageSize, int totalCount)
        {
            this.PageNumber = pageNumber;
            this.PageSize = pageSize;
            this.IndexFrom = pageNumber * pageSize;

            var itemList = source.ToList();
            this.TotalCount = totalCount;
            this.TotalPages = (int)Math.Ceiling(this.TotalCount / (double)this.PageSize);

            this.Items = itemList.Skip(this.IndexFrom).Take(this.PageSize).ToList();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{T}" /> class
        /// </summary>
        /// <param name="source">The Source Collection</param>
        /// <param name="pageNumber">The Page Number</param>
        /// <param name="pageSize">The Page Size</param>
        public PagedList(IQueryable<T> source, int pageNumber, int pageSize)
        {
            this.PageNumber = pageNumber;
            this.PageSize = pageSize;
            this.IndexFrom = pageNumber * pageSize;
            this.TotalCount = source.Count();
            this.TotalPages = (int)Math.Ceiling(this.TotalCount / (double)this.PageSize);
            this.Items = source.Skip(this.IndexFrom).Take(this.PageSize).ToList();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{T}" /> class
        /// </summary>
        public PagedList()
        {
            this.Items = new T[0];
        }
    }

    /// <summary>
    /// Provides the implementation of the <see cref="IPagedList{T}" /> and Converter
    /// </summary>
    /// <typeparam name="TSource">The type of the source.</typeparam>
    /// <typeparam name="TResult">The type of the result.</typeparam>
    public class PagedList<TSource, TResult> : IPagedList<TResult>
    {
        /// <inheritdoc />
        public int PageNumber { get; }

        /// <inheritdoc />
        public int PageSize { get; }

        /// <inheritdoc />
        public int TotalCount { get; }

        /// <inheritdoc />
        public int TotalPages { get; }

        /// <inheritdoc />
        public int IndexFrom { get; }

        /// <inheritdoc />
        public IList<TResult> Items { get; }

        /// <inheritdoc />
        public bool HasPreviousPage => this.PageNumber - this.IndexFrom > 0;

        /// <inheritdoc />
        public bool HasNextPage => this.PageNumber - this.IndexFrom + 1 < this.TotalPages;

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{TSource, TResult}" /> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="converter">The converter.</param>
        /// <param name="pageIndex">The index of the page.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="indexFrom">The index from.</param>
        public PagedList(IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> converter, int pageIndex, int pageSize, int indexFrom)
        {
            if (source is IQueryable<TSource> queryable)
            {
                this.PageNumber = pageIndex;
                this.PageSize = pageSize;
                this.IndexFrom = indexFrom;
                this.TotalCount = queryable.Count();
                this.TotalPages = (int)Math.Ceiling(this.TotalCount / (double)this.PageSize);

                var items = queryable.Skip((this.PageNumber - this.IndexFrom) * this.PageSize).Take(this.PageSize).ToArray();
                this.Items = new List<TResult>(converter(items));
            }
            else
            {
                this.PageNumber = pageIndex;
                this.PageSize = pageSize;
                this.IndexFrom = indexFrom;

                var itemList = source.ToList();
                this.TotalCount = itemList.Count;
                this.TotalPages = (int)Math.Ceiling(this.TotalCount / (double)this.PageSize);

                var items = itemList.Skip((this.PageNumber - this.IndexFrom) * this.PageSize).Take(this.PageSize).ToArray();
                this.Items = new List<TResult>(converter(items));
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{TSource, TResult}" /> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="converter">The converter.</param>
        public PagedList(IPagedList<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> converter)
        {
            this.PageNumber = source.PageNumber;
            this.PageSize = source.PageSize;
            this.IndexFrom = source.IndexFrom;
            this.TotalCount = source.TotalCount;
            this.TotalPages = source.TotalPages;
            this.Items = new List<TResult>(converter(source.Items));
        }
    }

    /// <summary>
    /// Provides some help methods for <see cref="IPagedList{T}" /> interface.
    /// </summary>
    public static class PagedList
    {
        /// <summary>
        /// Creates an empty of <see cref="IPagedList{T}" />.
        /// </summary>
        /// <typeparam name="T">The type for paging</typeparam>
        /// <returns>An empty instance of <see cref="IPagedList{T}" />.</returns>
        public static IPagedList<T> Empty<T>() => new PagedList<T>();

        /// <summary>
        /// Creates a new instance of <see cref="IPagedList{TResult}" /> from source of <see cref="IPagedList{TSource}" />
        /// instance.
        /// </summary>
        /// <typeparam name="TResult">The Type of the Result</typeparam>
        /// <typeparam name="TSource">The Type of the Source</typeparam>
        /// <param name="source">The Source</param>
        /// <param name="converter">The Converter</param>
        /// <returns>An instance of <see cref="IPagedList{TResult}" />.</returns>
        public static IPagedList<TResult> From<TResult, TSource>(IPagedList<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> converter) => new PagedList<TSource, TResult>(source, converter);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 ASP.NET 核心 mvc 向 ASP.NET 核心中的 Web API 发出 PUT 请求? - How to make a PUT request from ASP.NET core mvc to Web API in asp.net core? 如何测试我的 ASP.NET Core 2.2 Web API GET IActionResult 返回 Ok(object)? - How to test my ASP.NET Core 2.2 Web API GET IActionResult that returns Ok(object)? 如何将AzureAD和AzureADBearer添加到asp.net core 2.2 web api - How to add AzureAD AND AzureADBearer to asp.net core 2.2 web api 如何在ASP.Net Core 2.2 Web Api应用程序中连接到Amazon Kinesis Firehose - How to connect to Amazon Kinesis Firehose in ASP.Net Core 2.2 Web Api Application 如何通过ASP.NET Core 2.2向API发出PATCH请求? - How to make a PATCH request to am API with ASP.NET Core 2.2? 如何在 ASP.NET Core 2.2 API 中使用 Automapper - How to use Automapper with ASP.NET Core 2.2 API 如何使 PUT 从 ASP.NET MVC 到 ASP.NET 核心 Web ZDB974238714CA8A44A7CE1D0? - How to make PUT from ASP.NET MVC to ASP.NET Core Web API? Asp.net Web API筛选器优先级 - Asp.net Web API Filters priority ASP.NET core 2.2 web api 记录与数据保护密钥相关的警告:我们应该如何处理这个问题? - ASP.NET core 2.2 web api logs warnings related to data protection keys: how should we handle this issue? VueJs + ASP.Net Core Web API 发出 post 请求 - VueJs + ASP.Net Core Web API Make a post request
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM