Try our conversational search powered by Generative AI!

Steven Galton
Apr 10, 2018
  2881
(3 votes)

Managing Episerver Find Exceptions when querying the index

I have been working on the Episerver Find implementation here at Redweb for a client build. I was noticing that there were some errors that would occasionally happen when performing some queries against the index. After having a look around, I came across this article that gave me a solution to the issue and thought I would share the implementation into the project.

Firstly, I put a try catch around any of the Find services when they would be making a query against the index so that any errors would be caught. I can then check to see if the error is a ClientException or a ServiceException. If they are I can log the error with the exception to make sure there isn’t an issue with what we have written.

try
{
    var search = _findClient.Search<SupplierProduct>();

    if (!productCategoryId.IsNullOrWhiteSpace())
    {
        search = search.Filter(x => x.ParentCategory.Match(categoryId));
    }

    if (!string.IsNullOrWhiteSpace(queryString))
    {
        search = search.For(queryString).InField(x => x.Name);
    }

    if (!facetsList.IsNullOrEmpty())
    {
        search = search.MatchCategories(facetsList);
    }
    
    var supplierResults = search
        .ApplyBestBets()
        .UsingAutoBoost()
        .Skip((currentPage - 1) * resultsPerPage)
        .Take(resultsPerPage)
        .StaticallyCacheFor(TimeSpan.FromMinutes(1))
        .GetContentResult();

    return supplierResults;
}
catch (Exception ex) when(ex is ClientException || ex is ServiceException)
{
    Services.Episerver.Logger.Log(Level.Error, "Shop Search encountered an Episerver Find Exception", ex);
    return new EmptyContentResult<SupplierProduct>();
}

To make sure that the user has the best experience possible, a new type of content result was created. This means that if an error occurs an EmptyContentResult would be returned rather than an error. The new content result would have no results programmed set within the properties and can have the type passed into it so that it returns the correct class type for the search being performed.

public class EmptyContentResult<T> : ContentResult<T> where T : IContentData
{
    public EmptyContentResult() : base(
        Enumerable.Empty<T>(),
        new SearchResults<ContentInLanguageReference>(
            new SearchResult<ContentInLanguageReference>()
            {
                Facets = new FacetResults(),
                Hits = new HitCollection<ContentInLanguageReference>()
                {
                    Hits = Enumerable.Empty<SearchHit<ContentInLanguageReference>>().ToList()
                },
                Shards = new Shards()
            }))
    { }
}

This means that if any errors occur, although an empty page would show to the user, it would not break their view of the site and handle the error in an appropriate manner. This was very quick to implement across all the search methods on the site and also catches any of the errors that could occur out of our control.

I hope this helps some people out and I have also linked to the original source if anyone wants to look at it as well.

Apr 10, 2018

Comments

Antti Alasvuo
Antti Alasvuo Apr 10, 2018 06:42 PM

Hi, while exception handling is important I would disagree on the part where you claim to create better user experience by "hiding" the error from the user. I would say that you are creating bad experience and frustrating situation for the end-user. What ever they look for just returns no results (empty page or search result page saying "No results")? Why not honestly show the client that there was an error in the search and they can try the search later when the imaginary little dwarfs have corrected the astral projections that prevented the search to work ;)

Think about when you go to a web site and search for something

  • you get X results
  • you get message, sorry no results matched your query
  • you get Beep! Beep! 500 - Asteroids destroyed our search, we will fix it as soon as possible (launching rescue pods..)
  • according to your description user gets empty page

So I think telling the user there was an error on the server creates better user experience for the end user VS white page/no information that something actually went wrong.

Your code now only handles the Find related exceptions but what if there is a NullReferenceException or something else "a bug" in you code when you setup the query? Those are now bubbled up the stack and if not handled anywhere then you have the same situation as before adding the Find specific exception handling (so are you missing proper exception handling in higher the call stack? eventually (custom) error page if the exception is not handled in the code).

So it is unclear in the implementation fragment is it code from your search service implementation or block of code from your controller. If it is a service that you call from other code I would suggest to throw new Exception so that your calling code knows there was an Exception and there will be no results to show and if the caller then should show some error page or message in the search result view. Or another option is to return null to the caller and tell in the documentation that if there is an exception then the implementation will return null (and then the caller needs to have code for null check on return value - so this can always be argued to be bad practice, use exceptions for exception handling ;) )

There is a blog post about the Episerver Find exception types by Jonas Bergqvist in the Find blog.

Feb 12, 2019 08:58 AM

test

Feb 12, 2019 08:58 AM

test

Please login to comment.
Latest blogs
Upgrade Optimizely CMS From v11 to v12

Why Upgrade? There are many improvements implemented in version 12, but most importantly is that the whole framework is migrated from .Net Framewor...

MilosR | May 13, 2024

Configured Commerce - Infrastructure Updates Ahoy!

I'm very happy to share an important milestone - we no longer have any customers in our legacy v1 environment!  This means that the Configured...

John McCarroll | May 10, 2024

A day in the life of an Optimizely Developer - Enabling Opti ID within your application

Hello and welcome to another instalment of A Day In The Life Of An Optimizely developer, in this blog post I will provide details on Optimizely's...

Graham Carr | May 9, 2024

How to add a custom property in Optimizely Graph

In the Optimizely CMS content can be synchronized to the Optimizely Graph service for it then to be exposed by the GraphQL API. In some cases, you...

Ynze | May 9, 2024 | Syndicated blog

New Security Improvement released for Optimizely CMS 11

A new security improvement has been released for Optimizely CMS 11. You should update now!

Tomas Hensrud Gulla | May 7, 2024 | Syndicated blog

Azure AI Language – Key Phrase Extraction in Optimizely CMS

In this article, I demonstrate how the key phrase extraction feature, offered by the Azure AI Language service, can be used to generate a list of k...

Anil Patel | May 7, 2024 | Syndicated blog