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>>>
85
Product 85
Full description for product number 85
170.00 $
86
Product 86
Full description for product number 86
172.00 $
87
Product 87
Full description for product number 87
174.00 $
88
Product 88
Full description for product number 88
176.00 $
89
Product 89
Full description for product number 89
178.00 $
90
Product 90
Full description for product number 90
180.00 $
91
Product 91
Full description for product number 91
182.00 $
92
Product 92
Full description for product number 92
184.00 $
93
Product 93
Full description for product number 93
186.00 $
94
Product 94
Full description for product number 94
188.00 $
95
Product 95
Full description for product number 95
190.00 $
96
Product 96
Full description for product number 96
192.00 $
97
Product 97
Full description for product number 97
194.00 $
98
Product 98
Full description for product number 98
196.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);

        }

    }

}