THIS IS ARCHIVED DOCUMENTATION

LINQ QueryResults Example: Adding a Pager Section

Coveo for Sitecore (July 2016) Coveo for Sitecore 4.1 (November 2018)

This section contains information on how to add a pager section to your search page.

It uses the basic search page presented in LINQ QueryResults Example - Create a Basic Search Page.

Adding the Number of Results to Show

Add a new property in the SearchModel class. This property holds the number of results to show per page.

LinqBasedPageExample_2.aspx.cs

public class SearchModel {
    public const int DEFAULT_NB_RESULTS_PER_PAGE = 20;
    public string Query { get; set; }
    public int NbResultsPerPage { get; set; }
    public SearchModel() {
        Query = "";
        NbResultsPerPage = DEFAULT_NB_RESULTS_PER_PAGE;
    }
}

Add the following section to your page, after your query box. This TextBox contains the number of results to show per page.

LinqBasedPageExample_2.aspx

<div class="pagerSection">
    <asp:Literal Text="Results per page: " runat="server" />
    <asp:TextBox ID="NbResultsPerPage" Text="20" type="number" runat="server" />
</div>

Add the mapping between the model and the control.

LinqBasedPageExample_2.aspx.cs

private void MapControlsToModel(SearchModel model) {
    model.Query = Querybox.Text;
    model.NbResultsPerPage = int.Parse(NbResultsPerPage.Text);
}

You can now modify the LINQ query to handle the maximum number of results.

LinqBasedPageExample_2.aspx.cs

IQueryable<SearchResult> query = context.GetQueryable<SearchResult>()
                                        .CoveoOr(model.Query)
                                        .Take(model.NbResultsPerPage);

Your search page should now be restricted to the number of elements entered in the TextBox.

Adding the Pager to the Query

Add another property to the SearchModel. This property holds the current page number.

LinqBasedPageExample_2.aspx.cs

public class SearchModel {
    public const int DEFAULT_NB_RESULTS_PER_PAGE = 20;
    public string Query { get; set; }
    public int NbResultsPerPage { get; set; }
    public int Page { get; set; }
    public SearchModel() {
        Query = "";
        NbResultsPerPage = DEFAULT_NB_RESULTS_PER_PAGE;
        Page = 0;
    }
}

Add the following section to your page, after your number of results TextBox. This DropDownList contains every page that can be selected.

LinqBasedPageExample_2.aspx

<asp:Literal Text="Page: " runat="server" />
<asp:DropDownList ID="PageNb" AppendDataBoundItems="true" AutoPostBack="true" runat="server" />

The AutoPostBack="true" line ensures that the page gets refreshed when a new page is selected.

Add the following code to the MapControlsToModel method. This ensures that a page is selected before assigning it to the model.

LinqBasedPageExample_2.aspx.cs

if(!String.IsNullOrEmpty(PageNb.SelectedValue)) {
    model.Page = int.Parse(PageNb.SelectedValue);
}

The results are needed to show the number of pages available, so you need to add the following code to the RenderWithResults method. This adds all the possible values to the DropDownList so the user can pick any of them.

LinqBasedPageExample_2.aspx.cs

private void RenderWithResults(SearchModel model,
                               QueryResults<SearchResult> results) {
    LSTResults.DataSource = results.Results;
    LSTResults.DataBind();
    PageNb.Items.Clear();
    int numberOfPages = GetNumberOfPages(results.TotalCount, model.NbResultsPerPage);
    for(int i = 0; i < numberOfPages; i++) {
        PageNb.Items.Add(new ListItem(i.ToString(), i.ToString()));
    }
    // Keeps the selected value between PostBacks.
    PageNb.SelectedValue = model.Page.ToString();
}
 
private int GetNumberOfPages(double totalCount, int nbResultsPerPage) {
    return (int)Math.Ceiling(totalCount / nbResultsPerPage);
}

You can now modify your LINQ query to handle the current page.

LinqBasedPageExample_2.aspx.cs

IQueryable<SearchResult> query = context.GetQueryable<SearchResult>()
                                        .CoveoOr(model.Query)
                                        .Skip(model.NbResultsPerPage * model.Page)
                                        .Take(model.NbResultsPerPage);

Result

The result should look like this:

Client-Side Code

The client-side code should now look like this:

LinqBasedPageExample_2.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="LinqBasedPageExample.aspx.cs" Inherits="Tutorial.LinqBasedPageExample" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>LINQ-based Page Example</title>
</head>
<body>
    <form id="pageForm" runat="server">
        <div class="searchSection">
            <div>
                <asp:Literal Text="Query: " runat="server" />
                <asp:TextBox ID="Querybox" runat="server" />
            </div>
            <div class="pagerSection">
                <asp:Literal Text="Results per page: " runat="server" />
                <asp:TextBox ID="NbResultsPerPage" Text="20" type="number" runat="server" />
                <asp:Literal Text="Page: " runat="server" />
                <asp:DropDownList ID="PageNb" AppendDataBoundItems="true" AutoPostBack="true" runat="server" />
            </div>
            <asp:Button type="submit" Text="Run Query" runat="server" />
        </div>
        <div ID="ResultsSection" class="resultsSection" runat="server">
            <asp:GridView ID="LSTResults" AutoGenerateColumns="true" runat="server" />
        </div>
    </form>
</body>
</html>

Server-Side Code

The server-side code should now look like this:

LinqBasedPageExample_2.aspx.cs

namespace Tutorial {
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Coveo.Framework.SearchService;
    using Coveo.SearchProvider.Linq;
    using Coveo.SearchProvider.LinqBase;
    using Sitecore.ContentSearch;
    using Sitecore.ContentSearch.Linq;
    using Sitecore.ContentSearch.SearchTypes;
    public partial class LinqBasedPageExample : Page {
        protected void Page_Load(object sender, EventArgs e) {
            SearchModel searchModel = new SearchModel();
            if (Page.IsPostBack) {
                MapControlsToModel(searchModel);
                Render(searchModel);
            }
        }
        private void Render(SearchModel model) {
            if(!String.IsNullOrEmpty(model.Query)) {
                ClearResults();
                QueryResults<SearchResult> results = ExecuteQuery(model);
                if(results.TotalCount != 0) {
                    RenderWithResults(model, results);
                }else{
                    RenderWithoutResults(model, results);
                }
                RenderCommon(model, results);
            }
        }
        private void ClearResults() {
            LSTResults.DataSource = "";
            LSTResults.DataBind();
        }
        private void RenderWithResults(SearchModel model,
                                       QueryResults<SearchResult> results) {
            LSTResults.DataSource = results.Results;
            LSTResults.DataBind();
            PageNb.Items.Clear();
            int numberOfPages = GetNumberOfPages(results.TotalCount, model.NbResultsPerPage);
            for(int i = 0; i < numberOfPages; i++) {
                PageNb.Items.Add(new ListItem(i.ToString(), i.ToString()));
            }
            PageNb.SelectedValue = model.Page.ToString();
        }
        private void RenderWithoutResults(SearchModel model,
                                          QueryResults<SearchResult> results) {
            // No results handling.
        }
        private void RenderCommon(SearchModel model,
                                  QueryResults<SearchResult> results) {
            // Rendering with or without results.
        }
        private int GetNumberOfPages(double totalCount, int nbResultsPerPage) {
            return (int)Math.Ceiling(totalCount / nbResultsPerPage);
        }
        private QueryResults<SearchResult> ExecuteQuery(SearchModel model) {
            QueryResults<SearchResult> results;
            ISearchIndex index = ContentSearchManager.GetIndex("Coveo_web_index");
            using (var context = index.CreateSearchContext()) {
                  IQueryable<SearchResult> query = context.GetQueryable<SearchResult>()
                                                          .CoveoOr(model.Query)
                                                          .Skip(model.NbResultsPerPage * model.Page)
                                                          .Take(model.NbResultsPerPage);
                  results = query.GetCoveoQueryResults();
            }
            return results;
        }
        private void MapControlsToModel(SearchModel model) {
            model.Query = Querybox.Text;
            model.NbResultsPerPage = int.Parse(NbResultsPerPage.Text);
            if(!String.IsNullOrEmpty(PageNb.SelectedValue)) {
                model.Page = int.Parse(PageNb.SelectedValue);
            }
        }
    }
    public class SearchModel {
        public const int DEFAULT_NB_RESULTS_PER_PAGE = 20;
        public string Query { get; set; }
        public int NbResultsPerPage { get; set; }
        public int Page { get; set; }
        public SearchModel() {
            Query = "";
            NbResultsPerPage = DEFAULT_NB_RESULTS_PER_PAGE;
            Page = 0;
        }
    }
    public class SearchResult {
        public DateTime Date { get; set; }
        public string Title { get; set; }
        public string PrintableURI { get; set; }
    }
}