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>>>
43
Product 43
Full description for product number 43
86.00 $
44
Product 44
Full description for product number 44
88.00 $
45
Product 45
Full description for product number 45
90.00 $
46
Product 46
Full description for product number 46
92.00 $
47
Product 47
Full description for product number 47
94.00 $
48
Product 48
Full description for product number 48
96.00 $
49
Product 49
Full description for product number 49
98.00 $
50
Product 50
Full description for product number 50
100.00 $
51
Product 51
Full description for product number 51
102.00 $
52
Product 52
Full description for product number 52
104.00 $
53
Product 53
Full description for product number 53
106.00 $
54
Product 54
Full description for product number 54
108.00 $
55
Product 55
Full description for product number 55
110.00 $
56
Product 56
Full description for product number 56
112.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);

        }

    }

}