In this article I will explain with an example, how to implement Paging (Pagination) in ASP.Net Core MVC.
Paging (Pagination) will be implemented using Entity Framework in ASP.Net Core MVC.
Note: For beginners in ASP.Net MVC Core, please refer my article ASP.Net MVC Core Hello World Tutorial with Sample Program example.
 
 
Database
Here I am making use of Microsoft’s Northwind Database. You can download it from here.
Note: The Customers Table of the Northwind Database will be used in this project.
 
 
Downloading Entity Framework Core
You will need to install the Microsoft.EntityFrameworkCore.SqlServer package using the following command.
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 2.1.1
 
 
Model
Once the package is successfully installed, create a Folder named Models in your project and then a new class by right clicking the Models folder and then click on Add and then New Item option of the Context Menu. 
Then create the following properties inside the Model class.
The following Model class named CustomerModel consists of three properties.
1. Customers – List collection of the Customer Class which will hold the records of the Customers Table.
Note: In this article, only four Columns will be displayed and hence four properties are added to the class.
 
2. CurrentPageIndex – Holds the value of the index of the Current Page.
3. PageCount – This value is calculated using the Maximum Rows to be displayed and the Total Records present in the Table.
public class CustomerModel
{
    ///<summary>
    /// Gets or sets Customers.
    ///</summary>
    public List<Customer> Customers { get; set; }
 
    ///<summary>
    /// Gets or sets CurrentPageIndex.
    ///</summary>
    public int CurrentPageIndex { get; set; }
 
    ///<summary>
    /// Gets or sets PageCount.
    ///</summary>
    public int PageCount { get; set; }
}
 
public class Customer
{
    public string CustomerID { get; set; }
    public string ContactName { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
}
 
 
Database Context
1. Now you will need to add a new class to your project by right clicking the Solution Explorer and then click on Add and then New Item option of the Context Menu.
Paging (Pagination) example in ASP.Net Core MVC
 
2. Inside the class, first inherit the EntityFrameworkCore namespace and then inherit the DbContext class.
Then using Dependency Injection, a Constructor is created DbContextOptions are passed as parameter and also the Constructor of base class i.e. DbContext class is inherited.
Finally, a DbSet Collection property of Customer Model class is created, which will be later used for holding the Data fetched from SQL Server Database Table.
using Paging_EF_Core_MVC.Models;
using Microsoft.EntityFrameworkCore;
namespace Paging_EF_Core_MVC
{
    public class DBCtx : DbContext
    {
        public DBCtx(DbContextOptions<DBCtx> options) : base(options)
        {
        }
 
        public DbSet<Customer> Customers { getset; }
    }
}
 
 
Adding the Connection String inside AppSettings.json
The following Connection String setting has been added in the AppSettings.json file.
{
 "ConnectionStrings": {
    "MyConn""Data Source=.\\SQL2017;Initial Catalog=Northwind;Integrated security=true"
 }
}
 
 
Configuring Database Context in Startup class
Inside the Startup class, the IConfiguration is injected in the Startup class and assigned to the private property Configuration.
Then the Connection String is read from the AppSettings.json file and is used to add the DbContext service.
Note: For more details on reading Connection String inside the Startup class, please refer my article .Net Core: Read Connection String inside Startup.cs from AppSettings.json file.
 
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
namespace Paging_EF_Core_MVC
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
 
        public IConfiguration Configuration { get; }
 
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            string conStr = this.Configuration.GetConnectionString("MyConn");
            services.AddDbContext<DBCtx>(options => options.UseSqlServer(conStr));
        }
 
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
 
 
Controller
There are two Action methods with the name Index, one for handling the GET operation while other for handing the POST operation.
GetCustomers method
The GetCustomers method accepts currentPage parameter. It has a fixed variable named maxRows which determines the maximum records to be displayed per page.
Note: You can change the value of the maxRows variable as per your requirement and also fetch its value from AppSettings so that you don’t have to modify the code every time.
 
First an object of the CustomerModel class is created and then the records are fetched from the Customers table using Entity Framework and are set to the Customers property of the CustomerModel object.
The PageCount value is calculated by dividing the count of the records by the maximum rows to be displayed.
The currentPage parameter value is assigned to the CurrentPageIndex property.
The Paging is performed on the records using the Skip and Take functions.
The Skip function accepts the Start Index from the set of records to fetched i.e. if Page Index is 1 then the Start Index will be ( 1 - 1) * 10 = 0.
Example: If Current Page Index is 1 and the Maximum Rows is 10 then the Start Index will be (1 - 1) * 10 = 0
 
The Take function will fetch the rows based on the value of the maxRows variable.
GET operation
Inside the GET Action method, the GetCustomers method is called with the currentPage parameter value passed as 1 as when the View is accessed for the first time the records of the first page will be displayed.
POST operation
Inside the post Action method, the value of the CurrentPageIndex is passed to the GetCustomers method.
public class HomeController : Controller
{
    private DBCtx Context { get; }
    public HomeController(DBCtx _context)
    {
        this.Context = _context;
    }
 
    public IActionResult Index()
    {
        return View(this.GetCustomers(1));
    }
    [HttpPost]
    public IActionResult Index(int currentPageIndex)
    {
        return View(this.GetCustomers(currentPageIndex));
    }
 
    private CustomerModel GetCustomers(int currentPage)
    {
        int maxRows = 10;
        CustomerModel customerModel = new CustomerModel();
 
        customerModel.Customers = (from customer in this.Context.Customers
                                    select customer)
                    .OrderBy(customer => customer.CustomerID)
                    .Skip((currentPage - 1) * maxRows)
                    .Take(maxRows).ToList();
 
        double pageCount = (double)((decimal)this.Context.Customers.Count() / Convert.ToDecimal(maxRows));
        customerModel.PageCount = (int)Math.Ceiling(pageCount);
 
        customerModel.CurrentPageIndex = currentPage;
 
        return customerModel;
    }
}
 
 
View
Inside the View, in the very first line the CustomerModel is declared as Model for the View.
The View consists of an HTML Form with following ASP.Net Tag Helpers attributes.
asp-action – Name of the Action. In this case the name is Index.
asp-controller – Name of the Controller. In this case the name is Home.
method – It specifies the Form Method i.e. GET or POST. In this case it will be set to POST.
For displaying the records, an HTML Table is used. A loop will be executed over the Customers property of the CustomerModel class which will generate the HTML Table rows with the Customer records.
For building the Pager, a FOR loop is executed from value 1 to the value of the PageCount property for generating an HTML Table for Pager.
When a HTML Anchor inside the Pager is clicked a JavaScript function named PagerClick is executed which sets the Index of the clicked Pager button into a HiddenField and then submits the form.
@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers
@using Paging_EF_Core_MVC.Models;
@model CustomerModel
 
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width"/>
    <title>Index</title>
</head>
<body>
    <h4>Customers</h4>
    <hr/>
    <form asp-action="Index" asp-controller="Home" method="post">
        <table cellpadding="0" cellspacing="0">
            <tr>
                <th>CustomerID</th>
                <th>ContactName</th>
                <th>City</th>
                <th>Country</th>
            </tr>
            @foreach (Customer customer in Model.Customers)
            {
                <tr>
                    <td>@customer.CustomerID</td>
                    <td>@customer.ContactName</td>
                    <td>@customer.City</td>
                    <td>@customer.Country</td>
                </tr>
            }
        </table>
        <br/>
        <table cellpadding="0" cellspacing="0">
            <tr>
                @for (int i = 1; i <= Model.PageCount; i++)
                {
                    <td>
                        @if (i != Model.CurrentPageIndex)
                        {
                            <a href="javascript:PagerClick(@i);">@i</a>
                        }
                        else
                        {
                            <span>@i</span>
                        }
                    </td>
                }
            </tr>
        </table>
        <input type="hidden" id="hfCurrentPageIndex" name="currentPageIndex"/>
    </form>
    <script type="text/javascript">
            function PagerClick(index) {
                document.getElementById("hfCurrentPageIndex").value = index;
                document.forms[0].submit();
            }
    </script>
</body>
</html>
 
 
Screenshot
Paging (Pagination) example in ASP.Net Core MVC
 
 
Downloads