Simple Paging In ASP.NET Core Razor Pages

This article attempts to demonstrate how to implement simple paging functionality in a Razor Pages application. I will explain the basics behind paging, and then use BootStrap 4 to render a variety of paging links, without resorting to Nuget packages for link generation.

Three pieces of information are needed to implement paging:

  1. The current page number
  2. The total number of records to be displayed
  3. The number of records to display on each page (the page size)

Taking the simple approach, I add properties to the PageModel for each of these pieces of information:

The CurrentPage has a default value of 1, and the number of records per page (PageSize) is set at 10 by default. The CurrentPage has the BindProperty attribute applied so that it can automatically be bound from values passed as part of the request. It also has the SupportsGet property set to true specifically so that the query string or route data can be used to pass the value from request to request.

I also need to calculate the number of pages. I can do this by adding another property on the PageModel that performs the calculation:

Now all I need is some data. Usually this comes from a database, but I am using some dummy data formatted as JSON that's read from a file. My JSON will deserialise to a collection of Person objects:

So I also add a property to the PageModel for that:

Here is my PersonService class in full along with its interface:

This class is where I get my data from. It is analogous to a repository if you prefer that approach. It has two methods of interest: GetCount, which returns the total number of items to be displayed; and GetPaginatedResult, which returns the data for the current page. The GetPaginatedResult method uses the LINQ Skip and Take operators. Skip bypasses the specified number of items in the collection. If the CurrentPage is 1, Skip will bypass zero elements ((1-1) * 10). Then the Take method retrieves the specified number of elements from that point in the sequence. It will retrieve up to the number of elements represented by the pageSize parameter. Importantly, the order of the results is specified to ensure that the contents of each page of results are consecutive.

If you are using Entity Framework for your data access, the Skip and Take operators translate to using whichever paging function is supported by your database provider - the RowNumber function with a CTE, Offset and Fetch, Limit and Offset etc.

I register this service with the dependency injection system, and inject it into the PageModel where it is used in the OnGetAsync method to populate the Data and Count properties:

So here is the code for the content page:

When the page is run, the default values are used and the first 10 records are displayed, along with paging links for every page of records in the result:

Pagination in Razor Pages

As you hover over the paging links, you can see that the URLs generated by the anchor tag helper include a query string value for currentpage, which is the route value specified by the asp-route attribute:

Pagination in Razor Pages

If your prefer, you can remove the query string by adding a route template to the content page:

@page "{currentpage:int?}"

Now the currentpage value will appear as a segment in the URL:

Pagination in Razor Pages

Fine so far, but what if the space for the paging links is constrained or there are many more links? They will wrap onto the next line which won't look so good. One solution is to provide Prev and Next links, where the user can navigate from one page to the next and back again using just two buttons. To manage that, I add another pair of properties to the PageModel - ShowPrevious and ShowNext:

These properties are readonly expression bodied properties.They are used to determine whether the Previous and Next buttons should appear:

Razor Pages Pagination

This certainly saves space but could do with more improvement. So for the final tweak, I will add a First and Last button, and use FontAwesome icons to ensure that all of the links are the same size. So, two final properties are added to the PageModel - ShowFirst and ShowLast:

And the content page is amended accordingly:

Here is the finished result:

Razor Pages Pagination

On the first page, the Previous and First links are disabled, thanks to the styling from Bootstrap 4. They become active on subsequent pages:

Razor Pages Pagination

Summary

Pagination in Razor Pages is actually very simple once you get a grip of the basics. You can get very effective paging links rendered just by using the anchor tag helper and Bootstrap which is included as part of the standard Razor Pages project template. You don't need to create special ViewModel or wrapper classes for the properties required to manage pagination . You can easily add them to the PageModel instead - unless you are likely to want to reuse pagination throughout the application.