sitecoresitecore6datapager

DataPager controls use Sitecore layout URL instead of item URL


To implement a search results page on a Sitecore 6.3.1 site, I created a content item at /sitecore/content/Home/Search and added a Search Results sublayout to its presentation controls. The sublayout uses a ListView to display the search results and a DataPager to handle pagination.

Here is an excerpt from Search Results.ascx:

<asp:ListView ID="SearchResults" runat="server">
  <LayoutTemplate>
    <asp:DataPager ID="Pager" QueryStringField="page" runat="server">
      <Fields>
        <asp:NumericPagerField ButtonCount="10" />
      </Fields>
    </asp:DataPager>

    <asp:Placeholder ID="itemPlaceholder" runat="server" />
  </LayoutTemplate>

  ...
</asp:ListView>

Note that the DataPager's QueryStringField parameter is set to a non-empty value.

When the sublayout is rendered, the search results and pagination controls appear correctly. However, the pagination hyperlinks go to the wrong URL. Instead of going to the page URL, they link to the layout's URL.

For example, if the user clicks on the link for page 2, one would expect his browser to go to e.g., http://www.example.com/Search.aspx?query=xyz&page=2. But his browser actually links to http://www.example.com/layouts/Generic%20Browser%20Layout.aspx?query=xyz&page=2.

Where is the DataPager getting the bogus URL, and how do I fix this?


Solution

  • Here's the solution I ultimately went with. It's not pretty, but it does work:

    /// <summary>
    ///   Fixes any HyperLinks that point to the layout .aspx file to point to
    ///     the Sitecore context item.
    /// </summary>
    /// <param name="control">
    ///   The control to fix (its child controls will be processed).
    /// </param>
    protected void FixLayoutHyperLinks(Control control)
    {
      var currentPath = LinkManager.GetItemUrl(Sitecore.Context.Item);
      foreach (Control c in control.Controls)
      {
        foreach (Control d in c.Controls)
        {
          if (d is HyperLink)
          {
            var link = (HyperLink)d;
    
            /* Change just the path of the existing URL.
             * @see http://stackoverflow.com/questions/5276324/modifying-just-the-path-part-of-a-hyperlinks-navigateurl-in-c/5276375#5276375
             */
            var url = new UriBuilder(Request.Url.Host + link.NavigateUrl);
            url.Path = currentPath;
    
            /* For consistency (and because ASP.Net will strip the leading
             *  "http://" during PreRender), do not add the hostname/schema to
             *  the resulting URI.
             * 
             * @see http://sobot-software.blogspot.com/2009/02/asphyperlink-navigateurl-problem.html
             */
            link.NavigateUrl = url.Uri.PathAndQuery;
          }
        }
      }
    }
    

    I use it like so:

    private void Page_Load(object sender, EventArgs e)
    {
      ...
    
      var Pager = MyListView.FindControl("Pager") as DataPager;
      FixLayoutHyperLinks(Pager);
    }