Click here to Skip to main content
15,880,608 members
Articles / Web Development / ASP.NET / ASP.NET Core

Pagination in asp.net mvc core, entity framework and simplePagination.js

Rate me:
Please Sign up or sign in to vote.
3.00/5 (4 votes)
27 Jul 2017CPOL2 min read 22.3K   570   4   1
Sample application to demonstrate pagination using simplePagination.js in asp.net mvc core, targeting entity framework.

 

Introduction

This article will explain how to do pagination in asp.net mvc core application, targeting enity framework and using jquery template simplePagination.js.

One of my application I had to implement pagination, there are lot's of client side jquery templates are available, but the question is how to incorporate all those in to our application? This demo will walk through all the required bits and prices to do paging.

A generic class is provided to handle all the calculation, including reading page size from app.config files.

Background

This demo is not taking about how to create a new asp.net core mvc project or any programing language. I am indented to solve a problem generally.

Using the code

The code will do the following.

  • Get records from a source(hard coded)
  • Using a pagination helper to calculate and get the requested page
  • Pass the page to the view
  • Ask the simplePagination.js to render the pager
  • done!!!

Create a new .net core mvc application the project file would look like this

XML
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <OutputType>exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <ApplicationIcon />
    <OutputTypeEx>exe</OutputTypeEx>
    <StartupObject />
  </PropertyGroup>
  <ItemGroup>
    <Content Include="wwwroot\scripts\site.js" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
    <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.1.2" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics" Version="1.1.2" />
  </ItemGroup>
</Project

 

The startup.cs is setup to run mvc

C#
public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json");

            Configuration = builder.Build();
        }

        private IConfiguration Configuration { get; set; }

        public void ConfigureServices(IServiceCollection service)
        {
            service.AddMvc();

            service.AddSingleton(Configuration)
                .AddTransient(typeof(IPageHelper<>), typeof(PageHelper<>))
                .AddSingleton<IPageConfig, PageConfig>();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();

            app.UseStaticFiles();

            app.UseMvc(config => config.MapRoute("default", "{controller=Home}/{action=Index}/{id?}"));

            app.Run(handler => handler.Response.WriteAsync("Page not find."));
        }

A home controller added to show list of employees

HomeController will accept one constructor which will help preparing the pager. Usually pageHelper and _dbContext should be inside the business layer, for the readability I have using this directly inside controller.

C#
public class HomeController : Controller
    {
        private EmployeeDbContext _dbContext;
        private IPageHelper<EmployeeViewModel> _pageHelper;

        public HomeController(IPageHelper<EmployeeViewModel> pageHelper)
        {
            _dbContext = new EmployeeDbContext();
            _pageHelper = pageHelper;
        }

        [HttpGet]
        public IActionResult Index(int pageNumber = 1)
        {
            var allEmployees = _dbContext.GetEmployees();

            var result = _pageHelper.GetPage(allEmployees, pageNumber);

            var employees = new EmployeePageViewModel
            {
                Employees = result.Items,
                Pager = result.Pager
            };

            return View(employees);
        }
    }

 

Three interfaces are defined, in that IResultSet<T> will be the return type from GetPage()

 

C#
public interface IPageHelper<T>
{
    IResultSet<T> GetPage(IQueryable<T> items, int pageNumber);
}

public interface IPageConfig
{
    int PageSize { get; }
}

public interface IResultSet<T>
{
    IEnumerable<T> Items { get; set; }

    Pager Pager { get; }
}

 

And the model to store the page

 

C#
public class Pager
    {
        public int NumberOfPages { get; set; }

        public int CurrentPage { get; set; }

        public int TotalRecords { get; set; }
    }

 

Finally the implementation of IPageHelper<T>

Please note that GetPage accept a IQueryable<T> this can be changed to IEnumerable<T>

C#
public class PageHelper<T> : IPageHelper<T>
    {
        private readonly IPageConfig _pageConfig;

        public PageHelper(IPageConfig pageConfig)
        {
            _pageConfig = pageConfig;
        }

        public IResultSet<T> GetPage(IQueryable<T> items, int pageNumber)
        {
            var numberOfRecords = items.Count();
            var numberOfPages = GetPaggingCount(numberOfRecords, _pageConfig.PageSize);

            if (pageNumber == 0) { pageNumber = 1; }

            var pager = new Pager
            {
                NumberOfPages = numberOfPages,
                CurrentPage = pageNumber,
                TotalRecords = numberOfRecords
            };

            var countFrom = _countFrom(_pageConfig.PageSize, pageNumber);

            var resultSet = new ResultSet<T>
            {
                Pager = pager,
                Items = items.Skip(countFrom).Take(_pageConfig.PageSize)
            };

            return resultSet;
        }

        private readonly Func<int, int, int> _countFrom =
            (pageSize, pageNumber) => pageNumber == 1 ? 0 : (pageSize * pageNumber) - pageSize;

        private static int GetPaggingCount(int count, int pageSize)
        {
            var extraCount = count % pageSize > 0 ? 1 : 0;
            return (count < pageSize) ? 1 : (count / pageSize) + extraCount;
        }

        public class ResultSet<T> : IResultSet<T>
        {
            public IEnumerable<T> Items { get; set; }
            public Pager Pager { get; set; }
        }
    }

 

Add a bower.json to the project and add the required dependencies.

JavaScript
"dependencies": {
  "jquery": "3.2.1",
  "simplePagination.js": "*"
}

 

References to simplePagination.js and jquery.min.js are given to cshtml, and looping all the record using foreach

Pagination is defined in <ul id="emp-pagination" class="pagination"></ul>

This demo just contain one view so all the references are added here.

HTML
@model PagerDemo.ViewModels.EmployeePageViewModel

<script src="~/lib/jquery/dist/jquery.min.js"></script>
<link href="~/lib/simplePagination.js/simplePagination.css" rel="stylesheet" />
<script src="~/lib/simplePagination.js/jquery.simplePagination.js"></script>
<script src="~/scripts/site.js"></script>
<table>
    <tr>
        <th>Id</th>
        <th>First Name</th>
        <th>Last Name</th>
    </tr>
    @foreach (var emp in Model.Employees)
    {
        <tr>
            <td>@emp.Id</td>
            <td>@emp.FirstName</td>
            <td>@emp.LastName</td>
        </tr>
    }
</table>
<ul id="emp-pagination" class="pagination"></ul>

<input asp-for="Pager.NumberOfPages" type="hidden" id="hdnTotalNumberOfPages" value="@Model.Pager.NumberOfPages" />
<input asp-for="Pager.CurrentPage" type="hidden" id="hdnCurrentPage" value="@Model.Pager.CurrentPage" />

Next we will tell the somplepagination.js that id="emp-pagination" is a pagger. Please note that #hdnTotalNumberOfPages and #hdnCurrentPage are getting from the view (hidden field)

JavaScript
$(function () {
    $('#emp-pagination').pagination({
        pages: $('#hdnTotalNumberOfPages').val(),
        currentPage: $('#hdnCurrentPage').val(),
        itemsOnPage: 10,
        cssStyle: 'light-theme',
        onPageClick: function (pageNo) {
            var url = "/Home/Index?pageNumber=" + pageNo;
            window.location.href = url; 
        },
        hrefTextSuffix: '',
        selectOnClick: true
    });
});

 

When we run the application the result will be like this.

History

--

 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionPager Not Visible Pin
Member 133874505-Aug-18 9:32
Member 133874505-Aug-18 9:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.