3

I've a ListView with a DataPager the paging in the buttons (1,2,3,...) do not preserve the order of the parameters in querystring which is a bad thing in an SEO context (the bot thinks it is duplicate content).

I.E. if my page is:

Test.aspx?r=8&type=10
the pager buttons show:
Test.aspx?type=8&r=10&page=1
Test.aspx?type=8&r=10&page=2

etc... I think the control is ordering them in alphabetical order?

I've tried to override those URL's on the control PreRender() event, but it still renders the URL as described above...

Has anyone faced this issue??

Thanks.

ASPX:

  <asp:ListView ID="ListViewSearchResults" runat="server"  GroupItemCount="3" 
                    OnItemDataBound="ListViewSearchResults_ItemDataBound"        
   OnPagePropertiesChanging="ListViewSearchResults_PagePropertiesChanging" >
   ......
                </asp:ListView>

.....

    <asp:DataPager ID="ListViewPager" runat="server"  QueryStringField="page"          
    OnDataBinding="ListViewPager_DataBinding" OnPreRender="ListViewPager_PreRender"
    PagedControlID="ListViewSearchResults" PageSize="21"  >
    <Fields>
    <asp:NextPreviousPagerField  ShowFirstPageButton="true"          
    ShowPreviousPageButton="false" ShowNextPageButton="false"       
     ShowLastPageButton="false" ButtonCssClass="pagingright1"   ButtonType="Link"     
     FirstPageText=""  />
     <asp:NextPreviousPagerField ShowFirstPageButton="false"      
     ShowPreviousPageButton="true"   ShowNextPageButton="false" 
     ShowLastPageButton="false" ButtonCssClass="pagingright2"   ButtonType="Link" 
     PreviousPageText="" />                      
                    <asp:NumericPagerField  ButtonType="Link" CurrentPageLabelCssClass="pagingcurrent"  RenderNonBreakingSpacesBetweenControls="false" ButtonCount="10" />                       
                <asp:NextPreviousPagerField  ShowFirstPageButton="false" ShowPreviousPageButton="false" ShowNextPageButton="true" ShowLastPageButton="false" ButtonCssClass="pagingleft2"   ButtonType="Link"  NextPageText="" />
                <asp:NextPreviousPagerField ShowFirstPageButton="false" ShowPreviousPageButton="false"   ShowNextPageButton="false" ShowLastPageButton="true" ButtonCssClass="pagingleft1"   ButtonType="Link" LastPageText="" />

            </Fields>
        </asp:DataPager>

CS: trying to fix the links programmatically

    private void FixAllPagerLinks(string FixedUrl)
    {

    foreach (Control c in ListViewPager.Controls)
    {
        if(c.HasControls()) 
        {
            if(c.Controls[0] is HyperLink)
            {
                string PageParam = string.Empty; 
                string CurrentUrl = ((HyperLink)c.Controls[0]).NavigateUrl;
                char[] pageparam = new char[CurrentUrl.Length - CurrentUrl.IndexOf("page")];                    
                CurrentUrl.CopyTo(CurrentUrl.IndexOf("page"), pageparam, 0, CurrentUrl.Length - CurrentUrl.IndexOf("page"));
                PageParam = new string(pageparam);
                ((HyperLink)c.Controls[0]).NavigateUrl = string.Format("/{0}&{1}", FixedUrl , PageParam);
            }
        }
    }
}

    // in the DataPager PreRender Event nothing happen
    //but on page prerender event  it show the correct links but after 
    //clicking on next page in the pager it's messed up again
    protected override void OnPreRender(EventArgs e)
    {
    //getting the URL
    string NextPageurl = ((System.Web.UI.WebControls.HyperLink)        
    (ListViewPager.Controls[0].Controls[0])).NavigateUrl;
    //removing the page=1 to get the Basic url of the link
        NextPageurl = NextPageurl.Replace("&page=1", string.Empty).Replace("?page=1", string.Empty);
        string FullFixedUrl = FixQueryStringParameters(NextPageurl );
    FixAllPagerLinks(FullFixedUrl);
    }



private string FixQueryStringParameters(string QueryWithParams)
{
    string returnQueryStringParams = string.Empty;

    string p1 = string.Empty;
    string p2 = string.Empty;
    string p3 = string.Empty;
    Dictionary<string, string> QSKeyValuePairs = new Dictionary<string, string>();

    if (QueryWithParams.Split('?').Length > 1)
    {
        string parameters = QueryWithParams.Split('?')[1];

        if (parameters.Split('&').Length > 1)
        {
            p1 = parameters.Split('&')[0];
            QSKeyValuePairs.Add(p1.Split('=')[0], p1.Split('=')[1]);
            p2 = parameters.Split('&')[1];
            QSKeyValuePairs.Add(p2.Split('=')[0], p2.Split('=')[1]);

            if (parameters.Split('&').Length > 2)
            {
                p3 = parameters.Split('&')[2];
                QSKeyValuePairs.Add(p3.Split('=')[0], p3.Split('=')[1]);
            }
        }
    }
arik
  • 338
  • 1
  • 16

1 Answers1

1

The solution is to put the code that modifies the URL in the DataBound event of the related ListView. Here's my code to do this

ASPX:

<asp:DataPager PagedControlID="_lvCategoryProduct" PageSize="3" ID="dpProducts" runat="server" QueryStringField="p">
    <Fields>
        <asp:NextPreviousPagerField ButtonCssClass="lnkPager bold" PreviousPageText="Previous" ButtonType="Link" ShowFirstPageButton="False" ShowNextPageButton="False" ShowPreviousPageButton="true" />
        <asp:NumericPagerField CurrentPageLabelCssClass="selectedPager" NumericButtonCssClass="lnkPager pagerNumber" />
        <asp:NextPreviousPagerField ButtonCssClass="lnkPager bold" NextPageText="Next" ButtonType="Link" ShowLastPageButton="False" ShowNextPageButton="True" ShowPreviousPageButton="False" />
    </Fields>
</asp:DataPager>
<asp:ListView ID="_lvCategoryProduct" runat="server" GroupItemCount="3" ItemPlaceholderID="_phItems" GroupPlaceholderID="_phGroups">
    ...
</asp:ListView>

Page Code-behind:

protected void Page_Load(object sender, EventArgs e)
{
    _lvCategoryProduct.DataBound += _lvCategoryProduct_DataBound;
}
protected void _lvCategoryProduct_DataBound(object sender, EventArgs e)
{
    if (!String.IsNullOrEmpty(_dpProducts.QueryStringField))
    {
        Common.SetDataPagerUrls(_dpProducts);
    }
}

Methods in "Common" object

/// <summary>
/// Method to change DataPager URLs so they keep the URL Rewriting pattern
/// Code adapted from http://weblogs.asp.net/anasghanem/archive/2009/10/08/programmatically-modifying-the-hyperlinks-in-the-datapager-control.aspx
/// </summary>
/// <param name="pager">The DataPager for which we modify the URLS</param>    
static public void SetDataPagerUrls(DataPager pager)
{
    string queryStringField = pager.QueryStringField;

    //Rewrited URL is in Page.Request.RawUrl
    string rawUrl = pager.Page.Request.RawUrl;
    //Get the value of the current page =>  abc.aspx?[queryStringField]=[X]
    string currentQueryStringValue = pager.Page.Request[queryStringField];

    //Remove the current page querystring from the URL
    rawUrl = rawUrl.Replace(queryStringField + "=" + currentQueryStringValue,"");        
    //Remove the trailing "?" or "&"        
    if (rawUrl.EndsWith("?") || rawUrl.EndsWith("&"))
    {
        rawUrl = rawUrl.Substring(0, rawUrl.Length - 1);
    }

    string queryStringValue = "";    
    //Loop through the DataPager HyperLinks to modify the NavigateUrl   
    foreach (DataPagerFieldItem Pitem in pager.Controls)
    {
        foreach (Control c in Pitem.Controls)
        {
            if (c is HyperLink)
            {
                HyperLink link = c as HyperLink;
                //Get the page value for the link NavigateUrl
                queryStringValue = GetQueryStringNumericValue(queryStringField, link.NavigateUrl);

                //Set the new URL
                link.NavigateUrl = rawUrl;
                if (link.NavigateUrl.Contains("?"))
                {
                     link.NavigateUrl += "&";
                }
                else
                {
                     link.NavigateUrl += "?";
                }
                link.NavigateUrl += queryStringField + "=" + queryStringValue;                    
            }
        }
    } 
}

/// <summary>
/// Gets a numeric value of a querystring parameter in a URL
/// </summary>
/// <param name="queryStringField">The name of the querystring field</param>
/// <param name="url">The URL in which the querystring value must be found</param>
/// <returns></returns>
static protected string GetQueryStringNumericValue(string queryStringField, string url)
{
    string returnValue = "";
    //Regular expression will match value like "p=9" in a url like "abc.aspx?p=9" or "abc.aspx?a=1&p=9&..."
    string pat = queryStringField + @"=[0-9]+";
    Regex r = new Regex(pat, RegexOptions.IgnoreCase);
    MatchCollection m = r.Matches(url);
    if (m.Count > 0)
    {
        //Remove the "[parameter]=" to keep only the value
        returnValue = m[0].Value.Replace(queryStringField + "=", "");
    }
    return returnValue;
}
JF Menard
  • 93
  • 1
  • 12