Paging Techniques in .Net Core Web API
Consider a large data set displayed in a tabular format in a UI-based application. For example -
- Viewing a list of employees of a large services organization
- Viewing the details of bill of materials in a manufacturing business
- Viewing the list of patients in a hospital
In all these cases, if we apply a random filter - say restricting the list of patients' records of a hospital for a particular week or day. However, the list would still contain a lot of data that gets displayed on the page.
Now, displaying a huge amount of data will take a toll on the performance of the web application and result in a reduced user experience. So, to do the task efficiently, paging can be introduced in the client-side of the application which ensures that the UI provides a better experience for the user.
But the data that is being fetched from the database and back-end application remains the same, as it fetches the entire set of data. To optimize the back end and the data that is being fetched, a paging technique just like the one in the frontend can be implemented in the backend code to improve the performance and handle a smaller size of data at a time.
Let's see in detail how to achieve paging in the .net core web API.
Table of contents
- Introduction to Paging
- Implementing paging in .Net core web API
- Final Words
Introduction to Paging
Paging is a technique to achieve improved performance on fetching a large sum of data. It provides the user an option to configure the number of data that needs to be present on a single page and also to navigate page by page (either forward or reverse).
It takes rows per page and the column to sort as the primary input and provides only the requested data and the number of pages it has been split across.
Implementing Paging in .Net Core web API
To understand the implementation of paging in .Net Core Web API, we are going to create a .Net Core Web API and connect it with a database that has a table that stores the user's record. As a prerequisite to this, it is recommended to implement the code up to the point that is highlighted in our earlier blog.
The above blog will guide you on how to implement a new controller for getting the user's record. From here, we will make a few modifications and get it as a paged response.
As a first step, we need to create a new model where we obtain the following inputs from the user -
- Rows per page
- Columns to sort
- The current page which the user needs to see.
And you need to send the response with the input fields.
Go to the Models folder and add a new class file and name it as PagingModel and add the below content inside the file -
using System;
using System.Collections.Generic;
namespace PARTECH_Microservice.Models
{
public class PagingModel<T> where T: class
{
public int CurrentPage { get; set; }
public int TotalPages { get; set; }
public int RowsPerPage { get; set; }
public int TotalRows { get; set; }
public string OrderByData { get; set; }
public IEnumerable<T> Results { get; set; } = Array.Empty<T>();
}
}
You will get the total pages by dividing the total rows with rows per page.
The current page property denotes the current page for which the response is provided. And the results property holds the data that needs to be sent.
The next step is to Modify the UsersController- GetUserRecords method to take PagingModel as an input parameter and the same changes need to be made in the IUserService interface and the implementation class.
In Users Controller, add the below code -
[HttpGet]
public async Task<PagingModel<UserData>> GetUserRecords(**PagingModel<UserData> userInput**)
{
return await _userService.GetUserData(userInput);
}
For IUserService and UserSErvice class - public async Task<PagingModel<UserData>> GetUserData(PagingModel<UserData> inputData)
The next set of code is to write an extensions method for IQueryable where we are going to implement the logic to get the paged response.
Create a folder named - Extensions under the project and create a new class and name it as - QueryableExtensions.
Now you need to add the NuGet Package - System.Linq.Dynamic.Core.
Inside the class, add the below lines of code -
public async static Task<PagingModel<TInput>> GetPagedResult<TInput>(this IQueryable<TInput> query, int currentPage, int rowsPerPage, string orderBy, bool getAllRecords, string sortOrder = "asc")
where TInput : class
{
var sortOrderTerm = (sortOrder != "asc") ? " descending" : string.Empty ;
var finalQuery = String.IsNullOrWhiteSpace(orderBy) ? query : query.OrderBy(orderBy + sortOrderTerm);
var itemsToSkip = (currentPage - 1) * rowsPerPage;
var totalCount = finalQuery.Count();
var result = getAllRecords ? await finalQuery.ToListAsync() : await 9finalQuery.Skip(itemsToSkip).Take(rowsPerPage).ToListAsync();
return new PagingModel<TInput>
{
RowsPerPage = rowsPerPage,
CurrentPage = currentPage,
TotalPages = (totalCount / rowsPerPage),
TotalRows = totalCount,
Results = result
};
}
From the Userservice class and the Paging model input obtained from the request, the parameters for this extension method can be sent. And in the Userservice class, the get method needs to be modified as below -
public async Task<PagingModel<UserData>> GetUserData(PagingModel<UserData> inputData)
{
var query = _dbContext.UserData.AsQueryable();
var result = await query.GetPagedResult(inputData.CurrentPage, inputData.RowsPerPage, inputData.OrderByData, false);
return result;
}
Here, the dbcontext of UserData returns Iqueryable data. This is then used in the extensions method where it is altered to include the order by column and also to get a specific set of records from the database.
The added NuGet package is used to add the orderByData to be the final query.
On running the application and providing the below request in the body -
{
"CurrentPage": 1,
"RowsPerPage": 5,
"orderByData": "name"
}
We get the below response -
Final Words
Now that you have seen in detail the different paging techniques that can be followed in backend applications like Web API, it’s time to use it in your own application to get efficient, presentable, and quick output.