LINQ QueryResults Example: Create a Basic Search Page
LINQ QueryResults Example: Create a Basic Search Page
Coveo for Sitecore (July 2016) Coveo for Sitecore 4.1 (November 2018)
This page contains basic information on how to send a query and present you with the results.
Since this procedure will serve as the basis for the rest of the tutorial, you should keep a clean copy of it.
Basic Search Page
Start by creating a basic search page and a model that contains all the useful information needed to execute a query:
LinqBasedPageExample_1.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">
<asp:Literal Text="Query: " runat="server" />
<asp:TextBox ID="Querybox" runat="server" />
<asp:Button type="submit" Text="Run Query" runat="server" />
</div>
</form>
</body>
</html>
Server-Side Code Reference
This specifies which file to use as server-side code. If you change your file name, remember to change it here too.
LinqBasedPageExample_1.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="LinqBasedPageExample.aspx.cs" Inherits="Tutorial.LinqBasedPageExample" %>
Header
You can change this title to your liking, as it’s the title shown in the browser tab when the page is opened.
LinqBasedPageExample_1.aspx
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>LINQ-based Page Example</title>
</head>
Basic Form
This form contains the information sent to the server when the client sends a query.
The Querybox
TextBox contains the client query.
The submit
button ensures the client can click a button to send a query.
The searchSection
class can be styled to your liking. It’s currently shown solely to clarify this div
intention.
Most of the component this tutorial implements are going to be added to this form.
LinqBasedPageExample_1.aspx
<form id="pageForm" runat="server">
<div class="searchSection">
<asp:Literal Text="Query: " runat="server" />
<asp:TextBox ID="Querybox" runat="server" />
<asp:Button type="submit" Text="Run Query" runat="server" />
</div>
</form>
Base Server-Side File
These imports ensure that you have all the necessary assemblies for the full tutorial. Feel free to remove any of them if you don’t need them or you think they’re superfluous.
LinqBasedPageExample_1.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 {
}
}
Search Model
While this section may seem like it could be simpler for your current page, it will serve as a good basis for the rest of the tutorial.
In your server-side code, after the LinqBasedPageExample
class, create a model that contains all the useful information to execute a search query.
LinqBasedPageExample_1.aspx.cs
public class SearchModel {
public string Query { get; set; }
public SearchModel() {
Query = "";
}
}
Add a method in the LinqBasedPageExample
class that maps the Querybox
control value to the model.
LinqBasedPageExample_1.aspx.cs
private void MapControlsToModel(SearchModel model) {
model.Query = Querybox.Text;
}
It’s now possible to call this method in the Page_Load
method to map the controls to the model.
LinqBasedPageExample_1.aspx.cs
protected void Page_Load(object sender, EventArgs e) {
SearchModel searchModel = new SearchModel();
if (Page.IsPostBack) {
MapControlsToModel(searchModel);
}
}
The controls don’t have values when you first load the page, so it’s not necessary to call them outside of the PostBack.
Query Executer
When executing a query, you need an object that contains all the information you want to retrieve.
To contain the query fields, create a simple SearchResult
class.
LinqBasedPageExample_1.aspx.cs
public class SearchResult {
public DateTime Date { get; set; }
public string Title { get; set; }
public string PrintableURI { get; set; }
}
Feel free to add or remove fields to your liking.
Then, create a method called Render
containing all your rendering logic.
LinqBasedPageExample_1.aspx.cs
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)) {
QueryResults<SearchResult> results = ExecuteQuery(model);
// Do something with the results
}
}
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);
results = query.GetCoveoQueryResults();
}
return results;
}
Query Results Rendering
The following tag contains the search query results when the query has finished executing.
This could be added after the search section; however, you can put it anywhere on your page.
The AutoGenerateColumns="true"
attribute specifies that the columns are to be generated based on the object. In the tutorial, each property of the SearchResult
class is shown with its name and value.
LinqBasedPageExample_1.aspx
<div ID="ResultsSection" class="resultsSection" runat="server">
<asp:GridView ID="LSTResults" AutoGenerateColumns="true" runat="server" />
</div>
It’s now possible to bind the query results to the repeater.
The Render
method has been split in many sub-methods to clean the code and ease modularity through this tutorial.
- The
ClearResults
method clears the results on the page, ensuring there are no leftover results after a new query. - The
RenderWithResults
method is only called when the query has results. - The
RenderWithoutResults
method is only called when there are no results, and serves as feedback for the user when the entered query didn’t match any item. - The
RenderCommon
method is called after each query.
Most of the tutorials add code in one or more of these methods to render the correct information after a query. We recommend that you add your own code in these methods instead of using the Render method if needed.
LinqBasedPageExample_1.aspx.cs
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();
}
private void RenderWithoutResults(SearchModel model,
QueryResults<SearchResult> results) {
// No results handling.
}
private void RenderCommon(SearchModel model,
QueryResults<SearchResult> results) {
// Rendering with or without results.
}
Result
The search page is now queryable, and should look similar to the following screenshot.
Client-Side Code
The client-side code should now look like this:
LinqBasedPageExample_1.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">
<asp:Literal Text="Query: " runat="server" />
<asp:TextBox ID="Querybox" runat="server" />
<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_1.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();
}
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 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);
results = query.GetCoveoQueryResults();
}
return results;
}
private void MapControlsToModel(SearchModel model) {
model.Query = Querybox.Text;
}
}
public class SearchModel {
public string Query { get; set; }
public SearchModel() {
Query = "";
}
}
public class SearchResult {
public DateTime Date { get; set; }
public string Title { get; set; }
public string PrintableURI { get; set; }
}
}