Virtual Happy Hour this month, Jun 28, we'll be getting a sneak preview at our soon to launch SaaS CMS!

Try our conversational search powered by Generative AI!

Area: Optimizely Search & Navigation
ARCHIVED This content is retired and no longer maintained. See the latest version here.

Recommended reading 


Unified Search lets you index and query objects of existing classes without having to map them to an intermediate type that is put into the index.


Unified Search has four parts:
  • A common interface, ISearchContent, for declaring properties to use when building search (not querying) functionality.
  • An object that maintains a configurable list of types to be searched when searching for ISearchContent. Also, optionally, rules for filtering and projecting those types when searching IUnifiedSearchRegistry, which is exposed by the IClient.Conventions.UnfiedSearchRegistry property.
  • Classes for results returned when searching for ISearchContent: UnifiedSearchResults, which contain a number of UnifiedSearchHit.
  • Special methods for building and executing search queries: UnifiedSearch(), UnifiedSearchFor(), and an overloaded GetResult() method.


The ISearchContent interface resides in the EPiServer.Find.UnifiedSearch namespace and is the least common denominator. The interface declares several properties for which you may search, all of whose names begin with Search. Classes registered in Unified search do not have to implement ISearchContent. By having a property or extension method with the same name and type as a property in the interface, the property is treated as if it were received from the interface.

  • SearchTitle
  • SearchSummary
  • SearchText
  • SearchHitUrl
  • SearchTypeName
  • SearchHitTypeName
  • SearchSection
  • SearchSubsection
  • SearchAuthors
  • SearchGeoLocation
  • SearchPublishDate
  • SearchUpdateDate
  • SearchAttachment
  • SearchCategories
  • SearchFilename
  • SearchFileExtension
  • SearchMetaData
public class MySearchableClass
    public string Heading { get; set; }
    public string Body { get; set; }
    public string Url { get; set; }

    public virtual string SearchTitle { get { return Heading; } }
    public virtual string SearchSummary { get { return Body; } }
    public virtual string SearchText { get { return String.Format(CultureInfo.InvariantCulture, "{0} {1} {2}", Heading, Body, Url); } }
    public virtual string SearchHitUrl { get { return Url; } }
    public virtual string SearchSection { get { return GetType().Name; } }


IUnifiedSearchRegistry, also residing in EPiServer.Find.UnifiedSearch, exposes methods for building and configuring a list of types that should be included when searching for ISearchContent. In addition to methods for adding (the Add method) and listing types (the List method), IUnifiedSearchRegistry declares methods that let you add rules to filter specific types when searching and projecting found documents to the common hit type (UnifiedSearchHit).


UnifiedSearchResults and UnifiedSearchHit

While ISearchContent provides a decent common denominator for fields in which to search, it is not useful for getting back instances of it as the result of a search query. For instance, while you may want to search an indexed object's full text, you typically only want back a small text snippet to display in search results. Also, it is technically problematic to get instances of ISearchContent back from the search engine, since the matched object does not actually implement that interface, or at least it does not have to.

Therefore, when searching for ISearchContent and invoking the GetResult method, you do not get back instances of ISearchContent. Instead, you get an instance of the UnifiedSearchResults class, which contains several UnifiedSearchHit objects. A UnifiedSearchHit object contains properties that you would typically want to display for each search result, such as Title, URL and excerpt (text snippet). The UnifiedSearchHit object has additional properties, such as PublishDate, ImageUri, Section, FileExtension and TypeName.

Methods for building and executing queries

To search for ISearchContent, use the regular Search method, client.Search(). When doing so, you determine which fields to search when building free text search. Since ISearchContent is a special type that the .NET API knows about, two methods enable you to add sensible defaults: UnifiedSearch() and UnifiedSearchFor().

The Unified Search concept also provides a GetResult method. Since it has the same name as the regular method for executing search queries, you don't have to do anything special to use the GetResult method. Because it has a more specific generic-type constraint than other GetResult methods, the compiler uses it. Note that the GetResult method modifies search queries by searching for objects that implement ISearchContent and also for all types added to the UnifiedSearchRegistry. The GetResult method also adds a projection from ISearchContent to UnifiedSearchHit with sensible defaults, along with any type-specific projections added to the UnifiedSearchRegistry. Finally, before executing a search query (such as the GetResult method), Unified Search adds type-specific filters that were added to the UnifiedSearchRegistry.

When you invoke GetResult, the search query searches types that may not have implemented ISearchContent. But since you (hopefully) specified to only search in, or filter on, a number of fields declared by ISearchContent, the search only considers fields with those names, even if the objects do not implement ISearchContent. The GetResult method has an overload that requires an argument of type HitSpecification. This argument lets you control the length of the excerpt, whether to highlight titles and excerpts, and so forth.


Customize default projections

You can customize the projection of unified search results in several ways. The UnifiedSearchRegistry supports these options:

  • ProjectTitleFrom
  • ProjectTypeNameFrom
  • ProjectUrlFrom
  • ProjectImageUriFrom
  • UseHitType
  • ProjectHighlightedExcerptUsing
  • AlwaysApplyFilter
  • PublicSearchFilter
  • CustomizeProjection


To register the Title for a specific document type:

                .ProjectTitleFrom(x => x.MyTitleProperty);


To register the TypeName for a specific document type:

                .ProjectTypeNameFrom(x => x.MyTypeNameProperty);


To register the Url for a specific document type:

                .ProjectUrlFrom(x => x.MyUrlProperty);


To register the ImageUri for a specific document type:

                .ProjectImageUriFrom(x => x.MyImageUriProperty);


To register the type of the result item for a specific document type:



To register the highlighted excerpt for a specific document type:

                .ProjectHighlightedExcerptUsing<ISearchContent>(spec =>
                            x => x.MyHighlightedProperty.AsHighlighted(
                                new HighlightSpec { FragmentSize = spec.ExcerptLength, NumberOfFragments = 1 }));


To register a filter always applied for UnifiedSearch:

                .AlwaysApplyFilter(f => f.BuildFilter<MyType>().And(x => !x.MyProperty.Match("Something")));


To register a filter always applied for public UnifiedSearch:

                .PublicSearchFilter(f => f.BuildFilter<MySearchableClass>().And(x => !x.MyProperty.Match("Something")));


If the other projection options are inadequate, the CustomizeProjection extension provides full access to the HitProjectionBuilder.

Highlighting and encoding unified search results

For unified search results, HTML encoding is enabled by default for "title" and "excerpt" fields. The text is encoded before adding the HTML tags that surround highlighted content.


var hitSpec = new HitSpecification
HighlightExcerpt = true

// HighlightTitle = false by default,
// EncodeExcerpt = true by default,
// EncodeTitle = true by default


var result = searchClient.UnifiedSearchFor("apples").GetResult(hitSpec);

// result.Hits.First().Document.Excerpt contains I like <em>apples</em>.

Disabling HTML encoding

To disable HTML encoding, set the EncodeTitle and EncodeExcerpt properties of the HitSpecification to "false." If you do, ensure that the implementation handles the encoding of results, to ensure normal rendering and avoid script injections. You may also implement custom highlighting.


var hitSpec = new HitSpecification
HighlightExcerpt = true,
EncodeTitle = false,
EncodeExcerpt = false

var result = searchClient.UnifiedSearchFor("apples").GetResult(hitSpec);
// result.Hits.First().Document.Excerpt contains I like <em>apples</em>..


Do you find this information helpful? Please log in to provide feedback.

Last updated: Sep 21, 2015

Recommended reading