How to Implement Pagination in .NET Core MVC with Controllers and Razor Pages

Pagination is a crucial feature for any web application that deals with large amounts of data. It allows users to navigate through data easily without overwhelming them with too much information at once. In this post, we will explore how to implement pagination in a .NET Core MVC application using Controllers and Razor Pages. We will use a simple example to demonstrate the process.

Prerequisites

  • .NET Core SDK installed
  • Basic knowledge of ASP.NET Core MVC
  • Visual Studio or any preferred IDE

Step 1: Create a New ASP.NET Core MVC Project

First, create a new ASP.NET Core MVC project. Open your terminal or command prompt and run the following command:

dotnet new mvc -n PaginationExample
cd PaginationExample

Open the project in your preferred IDE.

Step 2: Set Up Your Data Model

For this example, we will use a simple data model. Let’s create a Product class in the Models folder:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Step 3: Create a Database Context

Set up Entity Framework Core to handle our data operations. Add a new class called AppDbContext in the Data folder:

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}

Register AppDbContext in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<AppDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddControllersWithViews();
}

Don’t forget to add your connection string in appsettings.json:

"ConnectionStrings": {
    "DefaultConnection": "Your_Connection_String_Here"
}

Step 4: Create a Controller

Create a ProductsController to handle product-related operations:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PaginationExample.Data;
using PaginationExample.Models;
using System.Linq;
using System.Threading.Tasks;

public class ProductsController : Controller
{
    private readonly AppDbContext _context;

    public ProductsController(AppDbContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index(int pageNumber = 1, int pageSize = 10)
    {
        var products = await PaginatedList<Product>.CreateAsync(_context.Products.AsNoTracking(), pageNumber, pageSize);
        return View(products);
    }
}

Step 5: Implement PaginatedList Helper Class

Create a helper class PaginatedList<T> to handle pagination logic. Add a new class file PaginatedList.cs in the Models folder:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

public class PaginatedList<T> : List<T>
{
    public int PageIndex { get; private set; }
    public int TotalPages { get; private set; }

    public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
    {
        PageIndex = pageIndex;
        TotalPages = (int)Math.Ceiling(count / (double)pageSize);

        this.AddRange(items);
    }

    public bool HasPreviousPage
    {
        get
        {
            return PageIndex > 1;
        }
    }

    public bool HasNextPage
    {
        get
        {
            return PageIndex < TotalPages;
        }
    }

    public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
    {
        var count = await source.CountAsync();
        var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
        return new PaginatedList<T>(items, count, pageIndex, pageSize);
    }
}

Step 6: Create Razor View for Displaying Products

Create a Razor view Index.cshtml under the Views/Products folder:

@model PaginatedList<Product>

@{
    ViewData["Title"] = "Products";
}

<h1>Products</h1>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.First().Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.First().Price)
            </th>
        </tr>
    </thead>
    <tbody>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Price)
            </td>
        </tr>
    }
    </tbody>
</table>

<div class="pagination">
    @if (Model.HasPreviousPage)
    {
        <a asp-action="Index" asp-route-pageNumber="@(Model.PageIndex - 1)" asp-route-pageSize="@ViewData["pageSize"]">Previous</a>
    }

    @for (int i = 1; i <= Model.TotalPages; i++)
    {
        <a asp-action="Index" asp-route-pageNumber="@i" asp-route-pageSize="@ViewData["pageSize"]" class="@(i == Model.PageIndex ? "selected" : "")">@i</a>
    }

    @if (Model.HasNextPage)
    {
        <a asp-action="Index" asp-route-pageNumber="@(Model.PageIndex + 1)" asp-route-pageSize="@ViewData["pageSize"]">Next</a>
    }
</div>

Step 7: Seed Data (Optional)

To see pagination in action, you might want to seed some data. Add the following code to your Startup.cs file:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AppDbContext context)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();

        // Seed data
        if (!context.Products.Any())
        {
            var products = new List<Product>();
            for (int i = 1; i <= 100; i++)
            {
                products.Add(new Product { Name = "Product " + i, Price = i });
            }
            context.Products.AddRange(products);
            context.SaveChanges();
        }
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Conclusion

You have successfully implemented pagination in a .NET Core MVC application using Controllers and Razor Pages. This approach ensures that your application handles large datasets efficiently, improving the user experience. You can further customize the pagination logic and the user interface to fit your application’s requirements. Happy coding!

Leave a Reply

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