LINQ QueryResults Example: Adding a Pager Section
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; }
}
}