Codegod - The page for .NET-developers
Winforms Grid TreeList Control .NET 2.0/3.5
GridView, performance and search-engines (SEO)
Developing a fast and search-engine friendly GridView (.NET 2.0)



The ASP.NET GridView is a powerful and userfriendly control for displaying a table of data. It has nice features like sorting, paging, databinding or templatefields. When loading a large amount of data, the paging feature can be used. But this leads to the following problems:
  • You have to get all the needed data at once and store it for paging. Most developers use the Session-object to store the needed data, which leads to memory problems when many users access the page.
  • The links for paging uses javascript which is not followed by the most search-engines. The result is, that only the links appearing on the first page of your GridView are indexed by search-engines.
To avoid this problems, you have to:
  • Get only the data you need for one page from database.
  • Implement a custom paging that uses GET-parameters and no javascript.
How this can be done is the topic of this article.

The standard

Here is a sample GridView with standard-implemenation that receives the data from a method GetData() : IList<String>
It has a PageSize of 5 and a Pager with First, Next, Previous and Last links:

Item
d466f3b6-2808-489b-a4e3-37b2435a3ebf
a582e95e-fa2d-405c-bf05-9cabd5e90c04
ec421e46-8153-43db-85db-7321f3aad65c
f180ab01-4b0d-484e-b728-9c6ada992620
496f73cb-6fd5-43a5-945c-1c889ab330c2
>>>

When moving the mouse over the links in the footer you can see the javascript that is executed when clicking. This is not very search-engine-friendly. The other drawback is, that the call GetData gets 100 items from the database but we need only 5 rows.

Enhancing the GridView

When enhancing the GridView to become fast and search-engine-friendly for large amount of data, you would implement a custom servercontrol. In this article we do not follow this approach, we just show inner implementation-details to achieve the enhancements. Here are the steps:

  1. Add a GridView from toolbox to the aspx-page
  2. Set AllowPaging to false
  3. Set the width of the GridView
  4. Add a DIV with a ASP:Literal below the GridView (DIV with same size as the GridView)
  5. Change you dataaccess-method so that you receive only the rows you need and the total number of rows
  6. Bind your GridView to the rows you received
  7. Add the links for paging to the Literal below the GridView

Okay, the first 3 steps are easy. Now for step 4. The DIV could look like this:

<DIV style="width: 400px; border: solid 1px #666666">
   <ASP:Literal ID="myPager" runat="server"></ASP:Literal>
</DIV>
 

The literal will hold the HTML-links. We will add these programmatically.

Step 5: Change the signature and implementation of the GetData-method:

IList<string> GetData( int currentPage, int rowCount, ref int totalRowCount )
{
  // 1. get only the data from currentPage to rowCount
  // 2. make a call that gets the number of all rows and store it in totalRowCount
  // return the IList<string> with all results for one page
}

Step 6: Binding is the same as before:

int total = 0;

// we have to store this before from a GET-param "page"
int currentPage = ViewState["page"];
gridView.DataSource= GetData( currentPage, gridView.PageSize, ref total );
gridView.DataBind();

// we store the totalRowCount cause we will need it when displaying the links
ViewState["Total"] = total;

Step 7: Adding the HTML-links for paging

For this step we need to add HTML-links programmatically. For demonstration we only add a previous and a next link.
Before we can do this, we have to store the GET-param "page" in the ViewState. If it is not set, we set it to 1. The methods SetPage and DisplayPager are called during Page_Load:

private void SetPage() {
  if (Request["Page"] == null)
      ViewState["Page"] = 1;
  else 
      ViewState["Page"] = Request["Page"].ToString();
}

Then the pager can be created. Each link in the pager gets the GET-param "page". This parameter is reused then by the method GetData to retrieve the rows we want to display.

private void DisplayPager() {
    int total = Convert.ToInt32(ViewState["Total"]);
    int page = Convert.ToInt32(ViewState["Page"]);
    int lastPage = (int)(total / gridView.PageSize );

    string pagerText = "";

    if( page != 1 )
        pagerText += GetUri( Request.Path, page - 1 );
    if( page < lastPage )
        pagerText += GetUri( Request.Path, page + 1 );

    myPager.Text = pagerText;
}

public string GetPagerUri(string url, int page ) {
    string result = "<a href='" + url + "?page" + page + "'>" + page + "</a>" ;
    return result;
}

Now we have a GridView that can load large amount of data in little chunks on demand and has a pager with links that can be found by search engines like google or yahoo. Try it, it is not hard to implement.