Update: Markis Taylor has extended my code and made the pager better. The code can be found here.

Over the last couple months I have been developing a site using Asp.Net MVC. For the most part I have enjoyed the experience but you definitely take some things for granted that are built into Asp.Net Web Forms. one of those things is the paging support that is built into the Gridview. MVC does have Html helpers for things like textboxes and drop downs but there is no built in support for paging.

 

Now that you have a little background on MVC, the problem I was facing was that we had several pages that were going to display results in lists and we needed a way for the user to be able to page through that data. While I probably could have found something written by someone else I decided to try and do this on my own. To accomplish this I decided to make an Html extension method. At the very least I needed to pass in the current page, the size of each page, and the total amount of records. I also chose to pass in the search criteria since i since i am passing the search parameters in the query string.

 

The first thing I did was find the total amount of pages by dividing the total by page size. if there was only one page I simply returned an empty string. Next I set an index based on the current page number and total pages. I needed to check to see if we were close to the end of the page count so that if there would be at most four links before the last page number.

 

After that I looped through creating the links that will be used for the paging extension. I hard coded a value of five so that the maximum amount of pages is never greater then five and i also try to keep every number but 1, 2 and the last two pages in the sequence in the middle. To create the links I created a Url helper by passing in the request context of the current helper. This is necessary in order to make the links that the pager will link to since we can’t create normal links in MVC because it does not go directly at the file system. I find this to be better than the paging in web forms because I can make the links contain the page number and search criteria in the query string. This way when you click on a pager link and then hit the refresh button it doesn’t give you a message asking if you want to re-post the page. Below is an example of the code used to create this extension. This is only a simple example so please don’t be too critical.

 

public static string Pager(this HtmlHelper helper, int currentPage, int pageSize, int total, string criteria)
        {
            UrlHelper u = new UrlHelper(helper.ViewContext.RequestContext);
            double totalPages = total * 1.0 / pageSize;
            // round total pages up to the nearest integer since we cant have something like 10.5 pages
            totalPages = (int)Math.Ceiling(totalPages);

            if (totalPages == 1)
                return string.Empty;

            int count = 0;
            int curIndex = 1;

            // needed for when we are toward the end of the page count
            // the else ensures that the current page will usually showup in the middle
            // with the exception of the first two pages
            if (currentPage == totalPages)
                curIndex = currentPage - 4;
            else if (currentPage == totalPages - 1)
                curIndex = currentPage - 3;
            else
                curIndex = currentPage - 2;

            TagBuilder t = new TagBuilder("span");
            StringBuilder sb = new StringBuilder();

            while (count < 5 && curIndex <= totalPages)
            {
                if (curIndex < currentPage && curIndex > 0)
                {
                    sb.Append(CreateLink(curIndex, criteria, u));
                    sb.Append("|");
                    count++;
                }
                else if (curIndex > currentPage && curIndex <= totalPages)
                {
                    sb.Append(CreateLink(curIndex, criteria, u));
                    sb.Append("|");
                    count++;
                }
                else if (curIndex == currentPage)
                {
                    sb.AppendFormat("<span>{0}</span>|", currentPage);
                    count++;
                }

                curIndex++;
            }

            if (sb.Length > 1)
                sb = sb.Remove(sb.ToString().LastIndexOf('|'), 1);

            t.InnerHtml = sb.ToString();

            return t.ToString();
        }

 

private static string CreateLink(int currentPage, string criteria, UrlHelper u)
        {
          

TagBuilder t = new TagBuilder("a");
            string address = u.Action("<Action>", "<Controller>", new { page = currentPage, startsWith = criteria });
            t.MergeAttribute("href", address);
            t.SetInnerText(currentPage.ToString());
            return t.ToString();


        }