Using ASP.NET 3.5's ListView and DataPager Controls: The Ultimate DataPager InterfaceBy Scott Mitchell
|A Multipart Series on ASP.NET's ListView and DataPager Controls|
This article is one in a series of articles on ASP.NET's ListView and DataPager controls, which were introduced with ASP.NET version 3.5.
The previous installment in this ongoing article series showed how to configure the DataPager control to generate an SEO-friendly paging interface. By default, the DataPager renders its paging interface as a series of Buttons, LinkButtons, or ImageButtons that, when clicked, trigger a postback. The problem with postbacks is that they are not crawled by search engine spiders, meaning that with the default behavior only the first page of data will make it into the search engines' indexes. Fortunately, the DataPager's paging interface can be configured to include the page number in the querystring. When configured this way, the DataPager renders its paging interface using hyperlinks with URLs like
Products.aspx?Page=PageNumber. With this approach a search engine will happily crawl through each page of data.
Shortly after publishing Creating an SEO-Friendly Paging Interface, a number of readers asked if it would
be possible to create a paging interface that moved the page number from the querystring into the URL. Rather than having a paging interface that linked to pages
with URLs like
Products.aspx?Page=PageNumber, these readers wanted to have URLs like:
Products/PageNumber. Such terse, descriptive URLs
are possible with ASP.NET Routing, a feature added to the .NET Framework 3.5 SP1. While typically used
in ASP.NET MVC applications, ASP.NET Routing can also be used in Web
This article shows how to use ASP.NET Routing with the ListView and DataPager controls to create the ultimate paging interface. Read on to learn more!
Please be sure to read Creating an SEO-Friendly Paging Interface before continuing on with this article...
Using ASP.NET Routing in the Paging Interface
One of the highlights of ASP.NET MVC is its ability to use ASP.NET Routing to create terse, "hackable", SEO-friendly URLs. While ASP.NET Routing is used by default in ASP.NET MVC applications, it can also be used in WebForm applications. Using ASP.NET Routing Without ASP.NET MVC gives detailed step-by-step instructions on what you need to do to start using ASP.NET Routing in a WebForms application.
In a nutshell, using ASP.NET Routing entails defining routing rules, which indicate what route patterns map to what ASP.NET pages. Consider the demo we looked at in
Creating an SEO-Friendly Paging Interface. In this demo we had a single ASP.NET page named
QueryStringPaging.aspx that used a ListView and DataPager to display
data from the Northwind database's
Products table. A querystring field named
Page was used to indicate the page of data to display. For example, to view
the first page of data we'd visit
QueryStringPaging.aspx?Page=1; to view the second page we'd visit
QueryStringPaging.aspx?Page=2; and so on.
Using ASP.NET Routing we can create a routing rule that defines a pattern of the form
/Products/PageNumber that maps to the ASP.NET page
QueryStringPaging.aspx?Page=PageNumber. With this routing rule in effect, a user can view the first page of products by visiting
/Products/1. To view the second page of data they'd visit
/Products/2, and so on. Such a routing rule gives us an ideal
URL for our product listing:
- The URL is very readable.
- The URL is "hackable." A user who is viewing the fourth page of data -
/Products/4- can infer that by removing the "/4" from the URL he will return to the first page of data.
- The URLs are SEO-friendly
- Configure the website to use ASP.NET Routing and implement the routing rules, and
- Customize the markup generated by the DataPager so that the paging interface renders hyperlinks that use the appropriate URLs -
Implementing ASP.NET Routing - Preamble
To use ASP.NET Routing in a WebForms application you need to perform five steps:
- Add a reference to
System.Web.Routingto your project.
- Add the
UrlRoutingModuleHTTP Module and
UrlRoutingHandlerHTTP Handler in
- Define the routes in
- Create the route handler class(es).
- Create the ASP.NET page(s) that process the requests.
Implementing ASP.NET Routing - Step 3: Defining The Routes In
Global.asaxfile can include event handlers for application-wide events. Whenever the application starts we need to define the routing rules. Therefore, these go in the
Application_Startevent handler. For this demo we need a single routing rule of the form
Products/Page. The following code implements this functionality:
Application_Start event handler fires whenever the application starts. It calls the
RegisterRoutes method, passing in the site-wide collection
of routing rules (
RegisterRoutes method then adds a new route. It starts by defining the default values for the route using
RouteValueDictionary. Specifically, a default value of 1 is defined for the Page parameter, which means if someone visits
/Products - that is,
there is no trailing page number - then a default page value of 1 will be used. The final line of code in the
RegisterRoutes method adds a new route rule to
the site-wide routes. The route is named
ProductRoute and the routing is handled by the
Implementing ASP.NET Routing - Step 4: Creating the Route Handler Class
When ASP.NET detects an incoming request of the form
/Products/somePageNumberit invokes the specified route handler class (
ProductRouteHandler). This route handler class is pretty straightforward. In short, it sends the user onto the ASP.NET page that contains the ListView and DataPager, which I've named
FancyPaging.aspx. It also needs to pass along the page number value in the route (such as 1, 2, etc.). This is passed from the
ProductRouteHandlerroute handler class to the
FancyPaging.aspxpage via the
Implementing ASP.NET Routing - Step 5: Creating the ASP.NET Page That Processes The Requests
FancyPaging.aspxpage uses ListView and DataPager controls to display the products from the Northwind database. A user may visit this page directly, by entering
FancyPaging.aspxin their browser's Address bar, or they may reach it indirectly via the routing rule defined in step 3.
FancyPaging.aspxis similar to the
QueryStringPaging.aspxpage examined in Creating an SEO-Friendly Paging Interface, with two notable exceptions:
QueryStringPaging.aspxthe DataPager would automatically inspect the querystring to determine which page to show. Since we've circumvented this process we need to write code for
FancyPaging.aspxthat displays the appropriate page of data based on the page specified through the route. Recall that this information is passed to
- The DataPager in
QueryStringPaging.aspxrendered its own paging interface with very little work on our end. We used NextPreviousPagerField and NumericPagerField controls in the DataPager's
<Fields>section to generate the paging interface. For
FancyPaging.aspxwe need to create the paging interface manually so that we can have the hyperlinks in the paging interface reference our custom URL structure (
/Products/pageNumberrather than the format the DataPager uses (
FancyPaging.aspx page is first visited we need to determine which page of data to display. The following code in the
Page_Load event handler
starts by reading in the requested page number from the
HttpContext.Items collection. Next, it computes the starting row index based on the page number and
how many rows to show per page. Finally, it calls the DataPager's
SetPageProperties method, passing in the starting row index, the maximum number of rows, and a
value of True that instructs the DataPager to have the ListView rebind its data to get the correct page of data.
ProductListPager is the
ID of the DataPager control on the page.
ProductListPager.PageSize specifies how many records to show
per page of data. The starting row index is computed by taking the requested page number, subtracting one, and then multiplying it by the number of records to show per page.
The starting row index and number of records to show per page are then passed into the DataPager's
SetPageProperties method, which instructs the DataPager to
go retrieve the appropriate page of data.
Generating the DataPager's Paging Interface
At this point the
FancyPaging.aspxpage can be visited via the route
/Products/pageNumber, which loads the appropriate page of products. However, the DataPager renders its paging interface with hyperlinks that send the user to
FancyPaging.aspx?Page=pageNumber. We need to update the DataPager's paging interface so that the hyperlinks send the user to
Unfortunately, the DataPager does not have a property you can set to customize the paging interface URL. Instead, we must use a TemplatePagerField and then craft the paging
interface's markup by hand. (For more information on using the DataPager's TemplatePagerField see Paging Through
Data with the ListView and DataPager Controls.) We are going to programmatically construct the markup for the paging interface, so our DataPager just needs an empty
<PagerTemplate> within the TemplatePagerField:
Then, in the ListView's
PreRender event, we can build up this paging interface (see the code below). The code starts by determining the current page being viewed
and the total number of pages. It then adds hyperlinks to the DataPager's template for the previous page, the next page, and numeric pages. Each paging interface hyperlink is
added to the template via a call to the
CreateLink method, which adds a Label Web control for disabled pager buttons, and a HyperLink Web control for enabled
NavigateUrl property of the HyperLink is assigned to the value returned by the
Helpers.FormatProductUrl(pageNumber) method, which
GetVirtualPath method to determine the appropriate routing URL for the specified page number.
The following two screen shots show the paging interface in action. The first screen shot shows the paging interface when first visited (
/Products). Note how the Previous
link is grayed out. Also note how the paging interface shows the last two page links, regardless of what page you're on. This lets the user quickly know how many total
pages of data there are.
The second one shows the paging interface when visiting 11th page of data (
/Products/11). Note how the first two paging links are always visible. This
enables users to quickly jump back to the beginning of the product list.