<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1639164799743833&amp;ev=PageView&amp;noscript=1">
Diagram Views

Developer Build: Indexing External Content with Episerver Find

John McKillip
#Episerver, #Code
Published on September 26, 2018
warren-wong-323107-unsplash-1

Diagram's John McKillip shares how he indexed external content using Episerver Find.

It's been over three years since I started developing Episerver applications, and let me tell you, I've loved every minute of it. In that time frame, the platform has been steadily evolving and getting better with each release. One of my favorite things to program in the applications that I build is the search implementation. In this regard, it's always a treat when the project has a budget to use Episerver Find. Find is a powerful tool for building simple to complex search experiences. From a developer perspective, I found it very easy to get started with Find. The documentation is decently robust and there is a great community of developers that are eager to help on the Episerver World Find forum.

I had an interesting requirement recently on an Episerver CMS build using Find. For this particular client, most of their content came from external RSS feeds and did not actually live in Episerver. They wanted the ability to search these external content feeds and return results with custom model data. Since there is no user interface built to do this (add feed urls, custom model data, etc.) by default in the CMS, I had to figure out how to do it programmatically. With Episerver and  Find, it was very simple to do. I ended up building a scheduled job that pulls the latest items from a feed and adds them to the Find index. Now for the fun part - let's take a look at some code!

Custom Feed Item Model

The main part of the code I am going to show you is on the scheduled job, but I wanted to first show you what my custom model for the news feed item looks like. Your model will depend on the requirements of your application. The same goes for your implementation of the class that reads the feed data. The main thing I wanted to point out in my custom model is that I implemented several of the UnifiedSearch ISearchContent fields, which is exactly what you want to do if you are going to use Episerver Finds Unified search.


public class NewsReleaseDetail : IShouldSearch
{
    public long CorpMasterID { get; set; }
    public long ReleaseID { get; set; }
    public string Title { get; set; }
    public string Date { get; set; }
    public string ReleaseText { get; set; }  

    public bool IsHiddenFromSearch { get; set; }

    // UnifiedSearch ISearchContent Fields
    public string SearchSection
    {
        get
        {
            return "CorporateContent";
        }
    }

    public string SearchTitle
    {
        get
        {
            return Title;
        }
    }

    public string SearchSummary
    {
        get
        {           
            return plainText.Truncate(200);
        }
    }

    public string SearchHitUrl
    {
        get
        {
            // This is a blank detail page that gets populated with data from the feed
            // Add your own implementation
            return SiteHelper.SiteSettings.NewsDetail.GetUrl() + "?id=" + ReleaseID;
        }
    }
}

public interface IShouldSearch
{
    bool IsHiddenFromSearch { get; set; }
}       

Scheduled Job Code

The code is pretty simple. I am using a class called FeedReader to work with the feed data. I get a list of the latest items, then loop through it. During each iteration, I create a NewsReleaseDetail model and add it to the Find index using IClient.Index().

gist:

https://gist.github.com/john-mckillip/6a5b76e385d3886e4283f3054172cbc5


[ScheduledPlugIn(
        DisplayName = "Index News Feed Items",
        Description = "",
        SortIndex = 0,
        DefaultEnabled = true,
        InitialTime = "1.1:0:0",
        IntervalLength = 24,
        IntervalType = ScheduledIntervalType.Hours)]
    public class IndexNewsItems : ScheduledJobBase
    {
        private bool _stopSignaled;
        private static IClient _client;
        private static readonly ILogger _logger = LogManager.GetLogger();

        public IndexNewsItems(IClient client)
        {
            _client = client;
            IsStoppable = true;
        }

        /// 
        /// Called when a user clicks on Stop for a manually started job, or when ASP.NET shuts down.
        /// 
        public override void Stop()
        {
            _stopSignaled = true;
            base.Stop();
        }

        /// 
        /// Called when a scheduled job executes
        /// 
        /// A status message to be stored in the database log and visible from admin mode
        public override string Execute()
        {
            //Call OnStatusChanged to periodically notify progress of job for manually started jobs
            OnStatusChanged("Starting execution of News Item Indexer");
            
            try
            {                
                // Get a list of all new news items from a feed
                // Add your own implementation of FeedReader.GetLatestNewsFeed()
                var newsItems = FeedReader.GetLatestNewsFeed();
                // Loop through the items, get the detail object and add it to the index.
                foreach (var item in newsItems)
                {
                    // Add your own implementation of FeedReader.GetNewsFeedDeatils(? id)
                    // Would return your custom news item model that will get indexed
                    var detail = FeedReader.GetNewsFeedDeatils(item.ReleaseID);
                    detail.IsHiddenFromSearch = false;
                    
                     // Add the item to your Find index
                    _client.Index(detail);
                }
            }
            catch (Exception ex)
            {
                _logger.Error("Index News Item Error: " + ex.ToString());

                return "Error. Check logs for details.";
            }

            //For long running jobs periodically check if stop is signaled and if so stop execution
            if (_stopSignaled)
            {
                Stop();
                return "Stop of job was called";
            }

            return "Success!";
        }
    }

And that is all there is to it. With very minimal effort, we now have external feed content in our Episerver Find index! Hopefully this will give you some insight as to how easy it is to work with external content and Episerver Find. If you have questions or feedback, please leave a comment below. If you are wondering how we could help you on your next Episerver Find implementation, contact us today!