Quick and Dirty Pagination


This entry is part [part not set] of 2 in the series API Endpoint Pagination

Let’s say you have an endpoint on your API that returns a list of objects, and it’s just no longer reasonable to expect it to return the entire list at once. It’s quite possibly time to introduce pagination. If you’ve never done this before it may sound a bit intimidating, but it doesn’t have to be. I’ve implemented endpoint pagination a couple of times. My first attempt was building some quick and dirty pagination, and although it got the job done it left me wanting to build a more robust solution. In this first post of the series, however, I’ll start by introducing you to the quick and dirty approach.

The request

The first thing you’ll need to do to support pagination is add a couple query parameters to the endpoint’s controller method.

[HttpGet("{customerId}")]
public ActionResult<List<Invoice>> Get(Guid customerId, int page, int pageSize)
{
    ...
}

The pageSize parameter allows the caller to specify how many objects are being requested. Imagine a book where each page has a list of objects of length pageSize. The page parameter would then specify which page of that book the caller is requesting.

The data layer

Implementing pagination in the repository is quite straightforward thanks to the Skip and Take methods provided by System.Linq.

public List<Invoice> Get(Guid customerId, int page, int pageSize)
{
    var offset = pageSize * (page - 1);
    return _dbContext.Invoices
        .Where(x => x.CustomerId == customerId)
        .Skip(offset)
        .Take(pageSize)
        .ToList();
}

The response

Now let’s update the controller method again. This time we’ll have it call the new repository method, and then return the results to the caller.

[HttpGet("{customerId}")]
public ActionResult<List<Invoice>> Get(Guid customerId, int page, int pageSize)
{
    return _invoiceRepository.Get(customerId, page, pageSize);
}

And that’s it. Some quick and dirty pagination. Please stay tuned for the second post in this series, where I’ll demonstrate a better, far more accommodating approach.

Series Navigation

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.