I was looking for a clean way to include pagination information for a RESTful Web API project. By clean way, I mean the page information (current page, total count, page size...) is not diluting my data model when returning the results and also if there is a standard way to do that in RESTful services.

I've seen some solutions adding custom headers to the response, which is not a bad way and keeps my model clean but what was really interesting is Github API implementation for "Traversing with Pagination" using the "Link" header.

The Http response link header is a standard HTTP header defined in RFC 5988 and can be used to specify links that is related to the document(s) returned in the response. In our case, this header will link to first. next, prev and last pages of the query results.

To give an example of how this link header work, in a response to a RESTful GET method that returns an array type of results, the link header will have URLs to retrieve the next page, last page, previous page and the last page -if any of these exist based on the results total count and page size).

A link header for the first page of queried entities with total count of 90 and page size of 10 will look something like this:

link:<https://yourServerHost.com/api/entities?page=2>; rel="next", 
<https://yourServerHost.com/api/entities?page=9>; rel="last"

The value between "<" ">" is the URL for the resource and the "rel" holds the relation metadata to the returned result, in this case "next" and "last" pages. The "first" and "prev" relations are not returned because they don't exist for the first page.

This now can be used by the client to build navigation UI allowing users to request these pages, the client also can figure out that there are 9 pages where each page size is the number of returned results (10).

An extension to Github implementation, the page size can also be provided in these URLs as a query parameter along with the page number to make it simpler for the client to generate its own URL to a specific page not provided in the link header.

link:<https://yourServerHost.com/api/entities?page=2&pgSize=10>; rel="next", 
<https://yourServerHost.com/api/entities?page=9&pgSize=10>; rel="last"

Let's get to the code!

On the server side, the solution is enabled by two main classes "PagedResult" and "LinkHeaderBuilder". The "PagedResult" class will take an IEnumerable, page number and page size to construct the information that helps us build the pagination links and the requested page result. While the "LinkHeaderBuilder" will take the PagedResult object and use its information to generate the value of the link header.

public static PagedResult<T> ToPagedResult<T> ( this IEnumerable<T> result, int pageNumber, int pageSize )
{
   return new PagedResult<T> ( result, pageNumber, pageSize ) ;
}

The Web API can now use this to wrap any IEnumerable type with a paged result object and use it to return the requested page along with information about retrieving other pages

    // GET api/PagingExample
    [HttpGet]
    public IEnumerable<AppEntity> Get( int? page, int? pgSize )
    {

        LinkHeaderBuilder linkBuilder = new LinkHeaderBuilder (  ) ;

        var entities    = _dataService.GetAllEntities ( page, pgSize ) ;
        var request     = Url.ActionContext.HttpContext.Request ;
        var uriBuilder  = new UriBuilder ( request.Scheme, 
                                           request.Host.ToUriComponent( ) ) {  Path = Url.Action ( ) } ;


        Response.Headers.Add ( "link", linkBuilder.GetLinkHeader ( entities, uriBuilder.ToString() ) ) ;

        return entities.Result ;
    }

The full solution along with a WebAPI example written in .NET core can be found on my Github PagedResult.Link project. It should be simple to also build it for any other .NET Framework versions.