Skip to content
Aaron edited this page May 18, 2019 · 5 revisions

The IPaginable interface is useful for presenting data one page at a time. This is useful in APIs as well as database queries.

The core of this functionality can be seen in 3 extension methods:

public static IEnumerable<T> GetPage<T>(this IEnumerable<T> collection, 
    int pageNumber, int pageSize)
{
    int skip = (pageNumber - 1) * pageSize;
    return collection.Skip(skip).Take(pageSize);
}

public static bool HasMorePages(this IPaginable collection)
{
    return collection.TotalResults > collection.PageNumber * collection.PageSize;
}

public static int GetPageCount(this IPaginable collection)
{
    decimal percent = collection.TotalResults / (decimal)collection.PageSize;
    return (int)Math.Ceiling(percent);
}

The IPaginable interface also enforces a data contract to remind you to provide the data in your API responses.

Usage

Given a database of addresses and a POCO AddressCollection class that implements IPaginable:

public AddressCollection LoadActiveAddresses(int pageNumber, int pageSize)
{
    int total;
    IList<Address> list;
    using (var context = new ImaginaryDataContext())
    {
        var query = from a in context.Addresses where a.IsActive select a;

        total = query.Count();  // this makes one call to the database
        var results = query.GetPage(pageNumber, pageSize);  // gets one page of data
        list = results.ToList();
    }

    return new AddressCollection
        { 
            TotalResults = total, 
            PageNumber = pageNumber, 
            PageSize = pageSize, 
            Addresses = list 
        };
}
Clone this wiki locally