In this article I will explain with an example, how to implement Custom Paging (Pagination) and Sorting using Entity Framework and jQuery in ASP.Net MVC Razor.
An HTML Table will be implement with Custom Paging (Pagination) using Entity Framework Skip and Take functions while Custom Sorting will be implemented using LINQ in ASP.Net MVC Razor.
 
 
Database
Here I am making use of Microsoft’s Northwind Database. You can download it from here.
 
 
Creating an Entity Data Model
The very first step is to create an ASP.Net MVC Application and connect it to the Northwind Database using Entity Framework. For more details please refer my article ASP.Net MVC: Simple Entity Framework Tutorial with example.
Following is the Entity Data Model of the Customers Table of the Northwind Database which will be used later in this project.
Custom Paging and Sorting using Entity Framework and jQuery in ASP.Net MVC
 
 
Model
The following Model class named CustomerModel consists of four properties.
1. Customers – List collection of the Customer Entity Data Model which will hold the records of the Customers.
2. PageIndex – Holds the value of the index of the Current Page.
3. PageSize – Holds the value of number of rows to be displayed per page.
4. RecordCount – Holds the value of the Total Records present in the Table.
public class CustomerModel
{
    public List<Customer> Customers { get; set; }
    public int PageIndex { get; set; }
    public int PageSize { get; set; }
    public int RecordCount { get; set; }
}
 
 
Controller
The Controller consists of two Action methods.
Action method for handling GET operation
Inside this Action method, simply the View is returned.
 
Action method for handling jQuery AJAX operation
This Action method handles the call made from the jQuery AJAX function from the View.
Note: The following Action method handles AJAX calls and hence the return type is set to JsonResult.
 
First an object of the CustomerModel class is created and then the records are fetched from the Customers table using Entity Framework and are assigned to the Customers property of the CustomerModel object.
The Custom 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 PageSize property.
A Switch case is used along with IF ELSE block in each case is used for Custom Sorting.
Each case is for a specific Column and within each case there is one IF ELSE block for Sort Direction i.e. Ascending or Descending.
Finally the CustomerModel object is returned to the View as JSON object.
public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        return View();
    }
 
    [HttpPost]
    public JsonResult AjaxMethod(int pageIndex, string sortName, string sortDirection)
    {
        NorthwindEntities entities = new NorthwindEntities();
        CustomerModel model = new CustomerModel();
        model.PageIndex = pageIndex;
        model.PageSize = 10;
        model.RecordCount = entities.Customers.Count();
        int startIndex = (pageIndex - 1) * model.PageSize;
 
        switch (sortName)
        {
            case "CustomerID":
            case "":
                if (sortDirection == "ASC")
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderBy(customer => customer.CustomerID)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                else
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderByDescending(customer => customer.CustomerID)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                break;
            case "ContactName":
                if (sortDirection == "ASC")
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderBy(customer => customer.ContactName)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                else
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderByDescending(customer => customer.ContactName)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                break;
            case "City":
                if (sortDirection == "ASC")
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderBy(customer => customer.City)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                else
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderByDescending(customer => customer.City)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                break;
            case "Country":
                if (sortDirection == "ASC")
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderBy(customer => customer.Country)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                else
                {
                    model.Customers = (from customer in entities.Customers
                                        select customer)
                            .OrderByDescending(customer => customer.Country)
                            .Skip(startIndex)
                            .Take(model.PageSize).ToList();
                }
                break;
        }
 
        return Json(model);
    }
}
 
 
View
The View consists of an HTML Table which will be populated with data from SQL Server database using jQuery AJAX and JSON.
The GetCustomers JavaScript function is called inside the jQuery document ready event handler, when the Header Column is clicked and also when the Pager Button is clicked.
Inside the GetCustomers JavaScript function, the value of the PageIndex, the SortName and the SortDirection values is sent to the Controller’s Action method using a jQuery AJAX call.
The Controller’s Action method returns a JSON object of the CustomerModel class which contains the List of Customers, the current Page Index, the Page Size and the total Record Count.
Using this JSON object and the dummy HTML row, the HTML Table is populated with the records returned by the Entity Framework.
The Pager is populated using the ASPSnippets_Pager jQuery Plugin.
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width"/>
    <title>Index</title>
    <style type="text/css">
        body {
            font-family: Arial;
            font-size: 10pt;
        }
 
        table {
            border: 1px solid #ccc;
            border-collapse: collapse;
            background-color: #fff;
        }
 
        table th {
            background-color: #B8DBFD;
        }
 
        table th, table td {
            padding: 5px;
            border: 1px solid #ccc;
        }
 
        table, table table td {
            border: 0px solid #ccc;
        }
 
        table th atable th a:visited{
            color: #333;
            font-weight: bold;
        }
 
        .Pager span {
            text-align: center;
            color: #333;
            display: inline-block;
            width: 20px;
            background-color: #B8DBFD;
            margin-right: 3px;
            line-height: 150%;
            border: 1px solid #B8DBFD;
        }
 
        .Pager a {
            text-align: center;
            display: inline-block;
            width: 20px;
            background-color: #ccc;
            color: #333;
            border: 1px solid #ccc;
            margin-right: 3px;
            line-height: 150%;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <h4>Customers</h4>
    <hr/>
    <table id="tblCustomers" cellpadding="0" cellspacing="0">
        <tr>
            <th><a href="javascript:;">CustomerID</a></th>
            <th><a href="javascript:;">ContactName</a></th>
            <th><a href="javascript:;">City</a></th>
            <th><a href="javascript:;">Country</a></th>
        </tr>
        <tr style="display:none">
            <td>CustomerID</td>
            <td>ContactName</td>
            <td>City</td>
            <td>Country</td>
        </tr>
    </table>
    <br/>
    <div class="Pager"></div>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script src="~/Scripts/ASPSnippets_Pager.min.js"></script>
    <script type="text/javascript">
        var sortName = "";
        var sortDirection = "ASC";
        $(function () {
            GetCustomers(1);
        });
        $("body").on("click", "#tblCustomers th a", function () {
            sortName = $(this).html();
            sortDirection = sortDirection == "ASC" ? "DESC""ASC";
            GetCustomers(1);
        });
        $("body").on("click", ".Pager .page", function () {
            GetCustomers(parseInt($(this).attr('page')));
        });
        function GetCustomers(pageIndex) {
            $.ajax({
                type: "POST",
                url: "/Home/AjaxMethod",
                data: '{pageIndex: ' + pageIndex + ', sortName: "' + sortName + '", sortDirection: "' + sortDirection + '"}',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: OnSuccess,
                failure: function (response) {
                    alert(response.d);
                },
                error: function (response) {
                    alert(response.d);
                }
            });
        };
        function OnSuccess(response) {
            var model = response;
            var row = $("#tblCustomers tr:last-child").removeAttr("style").clone(true);
            $("#tblCustomers tr").not($("#tblCustomers tr:first-child")).remove();
            $.each(model.Customers, function () {
                var customer = this;
                $("td", row).eq(0).html(customer.CustomerID);
                $("td", row).eq(1).html(customer.ContactName);
                $("td", row).eq(2).html(customer.City);
                $("td", row).eq(3).html(customer.Country);
                $("#tblCustomers").append(row);
                row = $("#tblCustomers tr:last-child").clone(true);
            });
            $(".Pager").ASPSnippets_Pager({
                ActiveCssClass: "current",
                PagerCssClass: "pager",
                PageIndex: model.PageIndex,
                PageSize: model.PageSize,
                RecordCount: model.RecordCount
            });
        };
    </script>
</body>
</html>
 
 
Screenshot
Custom Paging and Sorting using Entity Framework and jQuery in ASP.Net MVC
 
 
Downloads