ManuelAbadia.com
PagerDataSource samples
Samples



Product Information

Search Engine Optimization (Part 2)

The sample "Search Engine Optimization (1)" showed how to use the PagerDataSource control to obtain a navigable structure that is more search engine friendly. However, usually the spiders limit the number of pages to index that use dynamic parameters. For example, this is an excerpt of the Google FAQ:

"We're able to index dynamically generated pages. However, because our web crawler could overwhelm and crash sites that serve dynamic content, we limit the number of dynamic pages we index. In addition, our crawlers may suspect that a URL with many dynamic parameters might be the same page as another URL with different parameters. For that reason, we recommend using fewer parameters if possible. Typically, URLs with 1-2 parameters are more easily crawlable than those with many parameters."

There are some spiders that do not index any page with dynamic parameters so in order to further optimize the search engine positioning we can use an URL rewriter to transforms URLs like http://www.myserver.com/products.aspx?idCat=2idProd=34&Page=5 to URLs like http://www.myserver.com/idCat/2/idProd/34/Page/5/products.aspx where the parameters are part of the directory structure. There are a lot of URL rewriters on the net, some work at web server level, some are coded as ASP.NET HTTP Handlers or HTTP Modules, or even as a Virtual Path Provider. For the example we are going to use a free URL rewriter available at:

http://www.urlrewriting.net/

The PagerDataSource has two virtual methods that could be overridden in order to add support for URL rewriting. The methods are:

  • protected vritual bool TryGetCurrentPage(out int newPage);
  • protected virtual string GenerateUrl(int destinationPage);

The TryGetCurrenPage method is used to check if the current page has changed. The default implementation searchs for a query string parameter named as the PageKey. If the key is found, the method returns true and sets the newPage output parameter as the value for the PageKey.  The GenerateUrl returns a string with the URL to navigate when the user clicks a navigation link in the PagerDataSource when the control is in "QueryStringMode". The default implementation appends the current page to the query string under a parameter called PageKey.

In order to use the UrlRewriting module pointed above, we only need to inherit from PagerDataSource and override the GenerateUrl method in order to pass the parameters in the directory structure. The full source code is at the bottom of page. The URL rewriting module has been configured to rewrite URLs like this:

 

<urlrewritingnet

    rewriteOnlyVirtualUrls="true" 

    contextItemsPrefix="QueryString"

    xmlns="http://www.urlrewriting.net/schemas/config/2006/07" >

    <rewrites>

      <add name="RewritePages" virtualUrl="^~/(.*?)/(.*?)/(.*).aspx"

          rewriteUrlParameter="ExcludeFromClientQueryString"

          destinationUrl="~/$3.aspx?$1=$2"

          ignoreCase="true"/>

    </rewrites>

  </urlrewritingnet>


The source code for this page is shown after the live sample.


Product List

<<<1|2|3|4|5|6|7|8>>>
15
Product 15
Full description for product number 15
30.00 $
16
Product 16
Full description for product number 16
32.00 $
17
Product 17
Full description for product number 17
34.00 $
18
Product 18
Full description for product number 18
36.00 $
19
Product 19
Full description for product number 19
38.00 $
20
Product 20
Full description for product number 20
40.00 $
21
Product 21
Full description for product number 21
42.00 $
22
Product 22
Full description for product number 22
44.00 $
23
Product 23
Full description for product number 23
46.00 $
24
Product 24
Full description for product number 24
48.00 $
25
Product 25
Full description for product number 25
50.00 $
26
Product 26
Full description for product number 26
52.00 $
27
Product 27
Full description for product number 27
54.00 $
28
Product 28
Full description for product number 28
56.00 $
<<<1|2|3|4|5|6|7|8>>>

Sample source code

The ASPX file for this sample is:.


<%@ Page Language="C#" MasterPageFile="~/DefaultMaster.master" AutoEventWireup="true" CodeFile="SearchEngineOptimization2.aspx.cs" Inherits="SearchEngineOptimization2" Title="Search Engine Optimization" %>


<%
@ Register Assembly="PagerModified" Namespace="Manu.Web.UI.WebControls" 
    TagPrefix
="manuSamples" %>

 

<asp:Content ID="Content1" ContentPlaceHolderID="Content" Runat="Server">

    <h2>Product List</h2>

 

    <manuSamples:UrlRewritingPager ID="PagerDataSource1" runat="server"

        DataSourceID="ObjectDataSource1" PageSize="14" Mode="QueryStringRedirect">

    </manuSamples:UrlRewritingPager>

 

    <asp:DataList ID="DataList1" runat="server"

        DataKeyField="id" DataSourceID="PagerDataSource1"

        RepeatColumns="7" RepeatDirection="Horizontal" Width="100%">

        <ItemTemplate>

            <table>

                <tr>

                    <td align="center">

                        <asp:Label ID="idLabel" runat="server"

                        Text='<%# Eval("id") %>'></asp:Label>

                    </td>

                </tr>

                <tr>

                    <td align="center">

                        <b><asp:Label ID="nameLabel" runat="server"

                        Text='<%# Eval("name") %>'></asp:Label></b>

                    </td>

                </tr>

                <tr>

                    <td align="center">

                        <asp:Label ID="descriptionLabel" runat="server"

                        Text='<%# Eval("description") %>'></asp:Label>

                    </td>

                </tr>

                <tr>

                    <td align="center">

                        <asp:Label ID="priceLabel" runat="server"

                        Text='<%# Eval("price", "{0:#0.00}") %>'>

                        </asp:Label> $

                    </td>

                </tr>

            </table>

        </ItemTemplate>

        <ItemStyle BackColor="White" ForeColor="#436799" />

    </asp:DataList>

 

    <manuSamples:UrlRewritingPager ID="PagerDataSource2" runat="server"

        DataSourceID="PagerDataSource1" PageSize="14" Mode="QueryStringRedirect">

    </manuSamples:UrlRewritingPager>

 

    <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" TypeName="ProductsDAL"

        SelectMethod="GetPagedData" SelectCountMethod="CountAll" EnablePaging="True"

        MaximumRowsParameterName="maxRows" StartRowIndexParameterName="startIndex">

    </asp:ObjectDataSource>

</asp:Content>


The code-behind file (ASPX.CS) is:


using System;

 

public partial class SearchEngineOptimization2 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

    }

}


The code to generate URLs for the rewriting module is:


using System;

using System.Text;

using Manu.Web.UI.WebControls;

using UrlRewritingNet.Web;

 

namespace Manu.Web.UI.WebControls

{

    public class UrlRewritingPager : PagerDataSource

    {

            public override string GenerateUrl(int destinationPage)

        {

            // in design mode, delegate to the parent class

            if (DesignMode) {

                return base.GenerateUrl(destinationPage);

            }

 

            string urlPath, page;

 

            // get the current URL path and the current page

            GetUrl(out urlPath, out page);

 

            // creates a string builder to build the fake directory structure

            StringBuilder sb = new StringBuilder();

            sb.Append(urlPath);

            foreach (string key in Context.Request.QueryString.Keys) {

                // add the parameter if it's not the paging parameter

                if (String.Compare(key, PageKey) != 0) {

                    sb.Append(key);

                    sb.Append('/');

                    sb.Append(Context.Request.QueryString[key]);

                    sb.Append('/');

                }

            }

 

            // adds the paging parameter

            sb.Append(PageKey);

            sb.Append('/');

            sb.Append(destinationPage);

            sb.Append('/');

 

            // adds the page

            sb.Append(page);

 

            return sb.ToString();

 

        }

 

        public void GetUrl(out string urlPath, out string page)

        {

            // gets the URL of the request

            string url = Context.Request.Url.AbsoluteUri;

 

            // if the path has been rewriten, get the real path

            if (Context.Items[UrlRewriteModule.PhysicalPath] != null) {

                url = (string)Context.Items[UrlRewriteModule.PhysicalPath];

            }

 

            // deletes the query string from the url

            int queryCharIndex = url.IndexOf('?');

            if (queryCharIndex != -1) {

                url = url.Substring(0, queryCharIndex);

            }

 

            // extracts the page from the url

            int lastSlash = url.LastIndexOf('/');

            page = url.Substring(lastSlash + 1);

 

            // delete the page from the url

            urlPath = url.Substring(0, lastSlash + 1);

        }

    }

}