Jury-rig


Software Engineering, a personal journey

Roll your own pagination or why I did it the hard way and what I learnt along the way

One of the issues faced by every web developer is: How much reinventing the wheel do I do and what is the total benefit achieved by doing it a certain way? So here goes, why not use an off the self blogging system? Easy, there’s no fun using someone else’s solution plus it yields a massive knowledge debt

At what point does it become to expensive to roll your own? That’s a tough question I guess it’s when you use stuff you should be able to make yourself. I’m a C# .Net developer, mainly controller and model stuff. Using off the shelf for front end heavy lifting is acceptable to me because I don’t want a job in it but developing C# .Net knowledge is important. Pagination is a nice problem to get your head round and a pretty simple one to break down: How many things do you want to split in to pages How many things do you want on each individual page Where are you currently Can you go forwards from your current position Can you go backwards from your current position After an initial breakdown of the problem the next step is what is needed to answer the problem:
A thing model describing the thing you want paginating A pagination class describing useful stuff like location, things per page etc. MVC elements
Let’s be more specific and say we want to have a bunch of blog articles (say 5) displayed over enough pages to fit them all (say 17 articles for example). Calling a controller with a page number (but possibly not) should return a view with a model that describes a list of articles and enough data about pagination to create a list of links to all the articles in bunches of 5 whilst knowing where in the total list of articles it presently is. This bring up another requirement: an article model describing what an article looks like. So that totals 5 things: Model, View, Control, article model and pagination class. Now for the fun bit, what does the code look like? Hold your horses fella what about the UML diagrams, ok come on I’m joking (this isn’t for our day job).
Beginning with the MVC stuff, the view model needs to hold a list of articles and instantiate a pagination class. The view needs to use the model to construct href links to the paginated articles. Finally, the controller needs a nullable page number because we could have no articles or we could be at the home page with has no page number (starting point). Finally, we need an article model and a pagination class which could be used throughout the project and isn’t technically a model so let’s put it in a Domain folder.
https://github.com/juryrigcoder/DotNetMVCPagination
Model:
using System.Collections.Generic;

namespace demoMVC.Models
{
	public class HomeModel
	{
		public IEnumerable<ArticleModel> Items { get; set; } //articles to display
		public Pagination PaginationInformation { get; set; } //page information object for pagination
	}
}

View:
@model demoMVC.Models.HomeModel
<div>
    @foreach (var item in Model.Items)
    {
            <h2>
              @Html.Raw(item.Title)
            </h2>
    }
</div>

<ul>
	@if (Model.PaginationInformation.CurrentPage > 1)
	{
		<li>
			<a href="~/@Model.PaginationInformation.Location/Index">First</a>
		</li>
		<li>
			<a href="~/@Model.PaginationInformation.Location/Index?page=@(Model.PaginationInformation.CurrentPage - 1)">Previous</a>
		</li>
	}

	@for (var page = Model.PaginationInformation.CurrentPage; page <= Model.PaginationInformation.TotalPages; page++)
	{
		<li>
			<a href="~/@Model.PaginationInformation.Location/Index?page=@page">@page</a>
		</li>
	}

	@if (Model.PaginationInformation.CurrentPage < Model.PaginationInformation.TotalPages)
	{
		<li>
			<a href="~/@Model.PaginationInformation.Location/Index?page=@(Model.PaginationInformation.CurrentPage + 1)">Next</a>
		</li>
		<li>
			<a href="~/@Model.PaginationInformation.Location/Index?page=@(Model.PaginationInformation.TotalPages)">Last</a>
		</li>
	}
</ul>

Controller:
		public ActionResult Index(int? page)
		{
			var pageItems = ArticleItems();
			var articleModels = pageItems as IList<demoMVC.Models.ArticleModel> ?? pageItems.ToList();
			var pager = new Pagination("Home", articleModels.Count, page);

			var viewModel = new demoMVC.Models.HomeModel();
			{
				viewModel.Items =
					articleModels.Skip((int)((pager.CurrentPage - 1) * pager.PageSize)).Take((int)pager.PageSize);
				viewModel.PaginationInformation = pager;
			}
			return View(viewModel);
		}


Comments



Have your say

Author:

Comment here (140 chars only)*:

Email address: