Pagination in a .NET Core API Project
asp.net-core, c#, pagination, rest
Solution
There is no built-in feature for pagination, and if there was, you would not like it. Imagine a controller method returning 1.000.000 results for pagination just to pick 10 from them. It is up to you to implement the pagination.
The tedious and untidy controller methods like
public class FooController : Controller
{
public IEnumerable<Foo> GetAll(
string Filter,
string Whatever,
...,
int pageNumber = 1,
int pageSize = 20 )
{ ... }
}
can be reorganized to
public class FooController : Controller
{
public IEnumerable<Foo> GetAll( GetAllArgs args )
{
IQueryable<Foo> query = ...
return query.Paginate( args ).ToList();
}
public class GetAllArgs : QueryArgsBase
{
public string Filter { get; set; }
public string Whatever { get; set; }
}
}
public interface IPaginationInfo
{
int PageNumber { get; }
int PageSize { get; }
}
public abstract class QueryArgsBase : IPaginationInfo
{
public int PageNumber { get; set; } = 1;
public int PageSize { get; set; } = 20;
}
public static class QueryableExtensions
{
public static IQueryable<T> Paginate<T>(
this IQueryable<T> source,
IPaginationInfo pagination )
{
return source
.Skip( ( pagination.PageNumber - 1 ) * pagination.PageSize )
.Take( pagination.PageSize );
}
}
Change any other controller method to have such an argument class and inherite from `QueryArgsBase` or implement `IPaginationInfo` to use the `QueryableExtensions.Paginate` method.
Problem
I am trying to implement pagination on `.NET Core` `RESTful` API's (with `EF`). Rather than re-inventing the wheel, I was hoping there was a way to either use a generic function that could hook into the API handler and intercept requests to apply them to `EF` Query results or something built into `.NET Core` that I am un-aware of. Can anyone point me in the general direction of a library that they are aware of that does this in `.NET Core` The way I would previously do this (and have done in non .NET Core apps) is to make a function that I have to physically add the parameters to the controller function (pageSize, pageNumber) which does get tedious (and I think a tad untidy) to add these two parameters to every single function.