Jump To …

FindTemplate.aspx.cs

using System;
using EPiServer.Find;
using EPiServer.Find.Api.Querying.Queries;
using EPiServer.Find.Framework;
using EPiServer.Find.Cms;
using EPiServer.Find.UnifiedSearch;
using EPiServer.Templates.Alloy.Models.Pages;

namespace EPiServer.Templates.Alloy.Views.Pages
{
    public partial class FindTemplate : SiteTemplatePage<FindSearchPage>
    {

Create a "fresh" search request by redirecting to the CurrentPage's URL with the entered search query in the query string.

        protected void SearchButtonClick(object sender, EventArgs e)
        {
            var url = UriSupport.AddQueryString(CurrentPage.LinkURL, "q", tbQuery.Text);
            Response.Redirect(url);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

Show the entered search query in the input and execute the search. We only want to do this if the page isn't post back (the user hasn't pressed the search button) as we would otherwise ignore what the user has entered in the text box.

            if(!IsPostBack)
            {
                tbQuery.Text = Query;
                Search();
            }
        }

This is where the magic happens. We built up a search query based on query string parameters, execute it and populate the Results property which is then displayed in the ASPX markup.

        private void Search()
        {

Create a search/query for the entered search text retrieved from the query string.

            var query = SearchClient.Instance.UnifiedSearchFor(Query);

By default multiple words in the text entered by the user will be ORed, meaning that a search for Alloy Tech will be treated as Alloy OR Tech. Here we allow editors to instead use AND.

            if(CurrentPage.UseAndForMultipleSearchTerms)
            {
                var queryStringQuery = (IQueriedSearch<ISearchContent, QueryStringQuery>) query;
                query = queryStringQuery.WithAndAsDefaultOperator();
            }

Include a facet for sections.

            query = query.TermsFacetFor(x => x.SearchSection)

Include a facet whose value we can use to show the total number of hits regardless of section. The filter here is irrelevant but should match everything.

                    .FilterFacet("AllSections", x => 
                        x.SearchTitle.Exists() 
                        | !x.SearchTitle.Exists())

Fetch the specific paging page.

                    .Skip((PagingPage - 1) * PageSize)
                    .Take(PageSize)

Allow editors (from the Find/Optimizations view) to push specific hits to the top for certain search phrases.

                    .ApplyBestBets();

If a section filter exists (in the query string) we apply a filter to only show hits from a given section.

            if (!string.IsNullOrWhiteSpace(SectionFilter))
            {
                query = query.FilterHits(x => x.SearchSection.Match(SectionFilter));
            }

We can (optionally) supply a hit specification as argument to the GetResult method to control what each hit should contain. Here we create a hit specification based on values entered by an editor on the search page.

            var hitSpec = new HitSpecification
            {
                HighlightTitle = CurrentPage.HighlightTitles,
                HighlightExcerpt = CurrentPage.HighlightExcerpts,
                ExcerptLength = CurrentPage.ExcerptLength
            };

Execute the query and populate the Result property which the markup (aspx) will render.

            Results = query.GetResult(hitSpec);
        }

Property set by the Search method. Used as data source for the markup.

        protected UnifiedSearchResults Results { get; set; }

Retrieve the search query from the query string. If no such parameter exists we want to search for everything.

        protected string Query
        {
            get { return Request.QueryString["q"] ?? string.Empty; }
        }

The number of search hits to show in each result listing. By retrieving it from a property on the page we allow editors to control it.

        protected int PageSize
        {
            get { return CurrentPage.PageSize;  }
        }

Retrieve the paging page from the query string parameter "p". If no such parameter exists the user hasn't requested a specific page so we default to the first (1).

        protected int PagingPage
        {
            get
            {
                int pagingPage;
                if(!int.TryParse(Request.QueryString["p"], out pagingPage))
                {
                    pagingPage = 1;
                }

                return pagingPage;
            }
        }

Calculate the number of paged result listings based on the total number of hits and the PageSize.

        protected int TotalPagingPages
        {
            get
            {
                return 1 + (Results.TotalMatching-1) / PageSize;
            }
        }

Retrieve section filter from query string parameter, if any.

        protected string SectionFilter
        {
            get { return Request.QueryString["section"] ?? string.Empty; }
        }

Create URL for filtering by a specific section.

        protected string GetSectionFilterUrl(string section)
        {
            return UriSupport.AddQueryString(Request.RawUrl, "section", Server.UrlEncode(section));
        }

Create URL for a specific paging page.

        protected string GetPagingUrl(int pageNumber)
        {
            return UriSupport.AddQueryString(Request.RawUrl, "p", pageNumber.ToString());
        }
    }
}