I am on my third implementation of paging for blog posts, and finally am happy~ish with the implementation :). I first had an inline for loop (not very reusable), then I moved the code to a partial view (it was ok, but didn't feel quite right), and now I have finally settled on extending the HtmlHelper object.
I started off with ScottGu's PagedList<T> that I found on Rob Conery's blog. I made some small modifications based on my needs and preferences: download here. I basically ended up with IPagedList and IPagedList<T> interfaces and the PagedList<T> implementation itself. I needed the IPagedList<T> so that I could have strongly typed objects in the View, but the pager itself doesn't need to know the type. So, it gets the plain IPagedList.
Here is my Paging extension method:
public static string Paging(this HtmlHelper html, IPagedList pagedList,
string url, string pagePlaceHolder) {
StringBuilder sb = new StringBuilder();
// only show paging if we have more items than the page size
if (pagedList.ItemCount > pagedList.PageSize) {
sb.Append("<ul class=\"paging\">");
if (pagedList.IsPreviousPage) { // previous link
sb.Append("<li class=\"prev\"><a href=\"");
sb.Append(url.Replace(pagePlaceHolder, pagedList.PageIndex.ToString()));
sb.Append("\" title=\"Go to Previous Page\">prev</a></li>");
}
for (int i = 0; i < pagedList.PageCount; i++) {
sb.Append("<li>");
if (i == pagedList.PageIndex) {
sb.Append("<span>").Append( (i+1).ToString() ).Append("</span>");
} else {
sb.Append("<a href=\"");
sb.Append(url.Replace(pagePlaceHolder, (i+1).ToString()));
sb.Append("\" title=\"Go to Page ").Append( (i+1).ToString() );
sb.Append("\">").Append( (i+1).ToString() ).Append("</a>");
}
sb.Append("</li>");
}
if (pagedList.IsNextPage) { // next link
sb.Append("<li class=\"next\"><a href=\"");
sb.Append(url.Replace(pagePlaceHolder, (pagedList.PageIndex + 2).ToString()));
sb.Append("\" title=\"Go to Next Page\">next</a></li>");
}
sb.Append("</ul>");
}
return sb.ToString();
}
This is how you would invoke the method from a view:
<%= Html.Paging(ViewData.Model, Url.Action("Index","Blog", new { page = "__PAGENUM__" }), "__PAGENUM__") %>
As you can see, the method takes in an IPagedList, a URL with a placeholder for the page number, and the placeholder value itself. This way the pager can easily create links to the pages by simple replacing the placeholder with the page number desired.
After implementing this, I googled around to see if I had reinvented the wheel. I did find that Martijn Boland implemented a pager thats a bit more sophisticated. But does a pager class/method really need to know how to use the RouteTable to create URLs? I would prefer that it not. In fact, my code can be used in web forms and other non asp.net mvc projects.
Update (9/18/2008): Two more MVC paging related blog posts:

3 Responses to "Simple HtmlHelper Extension for Paging in ASP.Net MVC"
Please note that some responses may require approval before appearing.
papajuans says:
Thursday, September 18, 2008
Sweet. I love the "Show code in New Window" feature! I wonder who thought of that one.....
Ryan says:
Thursday, September 18, 2008
Gravatar?
Ricky says:
Thursday, September 18, 2008
thanks papajuans, you da man...