Category Archives: ASP.Net

AJAX paging for ASP.NET MVC sites

When working with lists of data paging is a necessity, but trivial to implement in an ASP.NET MVC. The article Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application on www.asp.net makes use of the X.PackedList.MVC NuGet package and each step is described in detail. The implementation requires full-page refresh and does not make use of AJAX capabilities.

Let us extend the implementation and make full use of the AJAX capabilities.

Wrap the entire table in a div-tag and give it an id of content – it will enable us to replace the table without refreshing the entire webpage.


<div id="content">

<table>
        ... removed for brevity
    </table>



<div id="contentPager">
        @Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
    </div>

</div>

Also wrap the @Html.PagedListPager in a div-tag and set the id to contentPager – it will let us alter the behavior of the click-event.

The below JQuery code attaches the anonymous function to every a-tag within the contentPager element and the function replaces the html within the content element with whatever is returned from the AJAX call.

$(document).on("click", "#contentPager a", function () {
    $.ajax({
        url: $(this).attr("href"),
        type: 'GET',
        cache: false,
        success: function (result) {
            $('#content').html(result);
        }
    });
    return false;
});

Move everything within the content element to a new view – let us call the new view List.

@model PagedList.IPagedList<ContosoUniversity.Models.Student>;
@using PagedList.Mvc;


<div id="content">

<table class="table">
      ... removed for brevity
    </table>



<div id="contentPager">
        @Html.PagedListPager(Model, page => Url.Action("List", new { page }))
    </div>

</div>

Notice in above highlighted code, that the Action URL is changed to List, which is the name of the Action we need to add to the StudentController.

public ActionResult List(int? page)
{
    var students = from s in db.Students
                    orderby s.LastName
                    select s;

    int pageSize = 3;
    int pageNumber = (page ?? 1);
    return View(students.ToPagedList(pageNumber, pageSize));
}

The functionality of the new List Action is the same as in the existing Index Action. Just move all the code from the Index Action, so it just returns the default view as below.

public ViewResult Index()
{
    return View();
}

To wrap it up, the Index view needs to call the List Action to render the table in the Index view.

So the Index view ends up looking like this.

<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
@{
    ViewBag.Title = "Students";
}

<h2>Students
<h2>

@Html.Action("List")

@section scripts
{
    <script language="javascript" type="text/javascript">
        $(document).ready(function () {
           $(document).on("click", "#contentPager a[href]", function () {
                $.ajax({
                    url: $(this).attr("href"),
                    type: 'GET',
                    cache: false,
                    success: function (result) {
                        $('#content').html(result);
                    }
                });
                return false;
            });
        });
    </script>
}

That is it.

The solution is inspired by this StackOverflow question.

Download the complete solution, build and open the Student page. If running the solution in Visual Studio 2015+, then change the data source connection string in web.config to (localdb)\MSSQLLocalDB as the default SQL Server LocalDB instance name has changed.

Update May 15th 2016: The PagedList.Mvc NuGet package is no longer maintained, but a fork of the project is available and maintained called X.PagedList.MVC. I have updated the post and the source to use this new package.

Juanster and others pointed out a bug in the sample, but it was actually in the PagedList.MVC. I created a pull request for X.PagedList.MVC, which is now part of the NuGet package.