For Part 2 – I implemented server side paging.
You can see demo here:
http://samples.entechsolutions.com/MvcGridSample/Part2
Code is available here:
http://samples.entechsolutions.com/Downloads/MvcGridSample/MvcGridSample_Part2.zip
Implementation
To add server side paging to grid I made the following changes:
1. Add page navigational controls to the View. For this I used a simple “<< >>” approach. The HTML for this was pretty straight forward.
2. Add page size control. For this task I used a drop down populated using a function on CustomerController:
html was:
<%= Html.DropDownList("pageSize", CustomerController.PageSizeSelectList(), new { onchange = "onPageSizeChange()" })%> rows per page
and function on CustomerController
public static SelectList PageSizeSelectList()
{
var pageSizes = new List {"1", "2", "5", "10", "100"};
return new SelectList(pageSizes, "Value");
}
3. Add JS code to make paging navigation and page size operational
//Set hidden variable to go to next/prev/last/first page and submit the form
function goToPage(pageIndex) {
$("#currentPage").val(pageIndex);
$("#gridAction").val("CurrentPageChanged");
submitForm();
}
//Set action performed in hidden variable. When PageSize changes - PageIndex needs to be
//reset to 1. This logic will go on the server side.
function onPageSizeChange(pageIndex) {
$("#gridAction").val("PageSizeChanged");
submitForm();
}
function submitForm() {
var form = $("#grid").parents("form:first");
form.submit();
}
4. Update CustomerController to perform paging using LINQ.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult List(int currentPage, int pageSize, string gridAction)
{
//Do logic depending on what action was performed
if (gridAction == "PageSizeChanged")
currentPage = 1;
//Check if there are no results. In this case return empty list.
IQueryable query = _customerService.GetQueryable();
int totalRows = query.Count();
if (totalRows==0)
return View(new List());
int totalPages = (int)Math.Ceiling((double)totalRows / (double)pageSize);
if (totalPages != 1)
{
//use LINQ to perform paging
query = query.Skip((currentPage - 1) * pageSize)
.Take(pageSize);
}
//Update ViewData collection to display pager stats and pager controls
UpdatePagerViewData(totalPages, totalRows, currentPage, pageSize);
List customers = query.ToList();
return View(customers);
}
5. Cleanup CSS and table structure. This part took majority of the time. At first I was thinking of just using CSS and Divs for pager, but after having some issues with getting navigational control positioned in the middle, I decided to go with a table approach. In the end I ended up using a combination of Divs and CSS.
Observations
- Using ViewData to pass information from Controller to View is getting heavy. I am currently passing 5-10 variables just for the pager. I think it makes sense to create data structure GridModel/Grid to hold all the variables. This approach has the following advantages:
1. Strong typing using “if (gridModel.IsFirstPage) then ” instead of “if (bool)ViewState(“IsFirstPage”)“
2. Can keep call CustomerController.List(…) clean by using “UpdateModel(gridModel);” instead of passing more and more arguments to CustomerController.List(…);
3. Will be able to compartmentalize Pager and Sorter using object hierarchy. For ex. GridModel.Pager.PageIndex, GridModel.Sorter.SortField, etc… -
Noticed something weird in CSS. Using CSS class like:
#grid #pager #navButtons table tr td .disabled { color: #C0C0C0; text-align: center; }does not work. But if I change it to:
#grid #pager #navButtons .disabled { color: #C0C0C0; text-align: center; }it will work. I wonder if CSS selectors don’t allow for matching “id tag class”.
For Part 3
In upcoming part 3, I will implement server side sorting.

