I bought Steve Sanderson’s book Pro ASP.NET MVC about 6 months ago and I must admit its a real winner for the single reason that the code and explanations are clear and to the point, and he actually gives you code you can use easily. In chapter 4 he builds a paging helper class which is really cool and works well when you bind the model to your view but the way he implements it could be made better by creating a class that accepts a generic type and I also want to use this method for Ajax/jQuery. The code in his book for the PagingInfo class looks like this:
public class PagingInfo
{
public int TotalItems { get; set; }
public int ItemsPerPage { get; set; }
public int CurrentPage { get; set; }
public int TotalPages
{
get
{
return (int)Math.Ceiling(decimal)TotalItems / ItemsPerPage;
};
}
}
In the controller in his book he then creates a class called, ProductsListViewModel, which has two properties, IList
Products and PagingInfo PagingInfo:
public class ProductsListViewModel
{
public IList
Products { get; set; }
public PagingInfo PagingInfo { get; set; }
}
On a side note I must say I agree in part with Jeffrey Richter in his book C# via CLR that properties are a weird mix of a method and not a method and sometimes it does feel as if what you are doing in a property might work in a method also. But I digress. In his controller he has a action result that binds the ProductsListViewModel to the view:
public ViewResult List([DefaultValue(1)] int page)
{
var productsToShow = productsRepository.Products;
var viewModel = new ProductsListViewModel
{
Products = productsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList();
PagingInfo = new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = productsToShow.Count()
}
}
return View(viewModel);
}
Before I continue there are a few things to note about the controller method and the first is that I have not shown the productsRepository and its implementation and the second thing to note is that PageSize is a public variable declared in the controller class.
The code works great, and I have used it now in several places and I really like it because it feels as if the PagingInfo class provides an abstraction that the entity you are paging does not know about. This makes it feel light and easy to implement. I do however think it might be useful to create a class that accepts a generic type instead. So what I have done is create a class called EntityViewModel, and it looks a bit like this:
public class EntityViewModel
{
private List listOfEntities;
private PagingInfo pagingInfo;
public List ListOfEntities
{
get { return listOfEntities; }
set { this.listOfEntities = value; }
}
public PagingInfo PagingInfo
{
get { return pagingInfo; }
set { this.pagingInfo = value; }
}
}
This will mean that when I create a controller method I can do this instead:
public ViewResult List([DefaultValue(1)] int page)
{
var productsToShow = productsRepository.Products;
var viewModel = new EntityViewModel
{
ListOfEntities = productsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList();
PagingInfo = new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = productsToShow.Count()
}
}
return View(viewModel);
}
Which to me seems a bit more flexible. It doesnt end there though because I want to consume the controller method using jQuery and jQuery templates and for that I need to change the controller method slightly:
public JsonResult List([DefaultValue(1)] int page)
{
var productsToShow = productsRepository.Products;
var viewModel = new EntityViewModel
{
ListOfEntities = productsToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList();
PagingInfo = new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = productsToShow.Count()
}
}
return Json(viewModel);
}
Now I can get a JSON result, AND it has paging which is totally awesome!