Extending Computed Fields in Sitecore By Adding Parameters

Creating Powerful, Reusable Computed Fields

Computed Fields In Sitecore

The purpose of computed fields is to create pre-calculated values when working with indexes. And in Sitecore we'll be using an index-centric approach when trying to retrieve large amounts of data from disparate areas of the content tree.

They have lots of interesting use-cases. I'll assume you've found this post because you've already discovered one. My goal is to share some tips to help people get the most of them.

Anatomy Of A Computed Field

By default computed field a limitation - poor reusability. This is because it's doesn't naturally lend itself to variable inputs.

It looks like this with fieldName being the only parameter. This controls the name of the field with the value output by Sitecore.ContentSearch.ComputedFields.Culture will be stored.


<field fieldName="culture">Sitecore.ContentSearch.ComputedFields.Culture,Sitecore.ContentSearch</field>

We'll look at how to add parameters to computed field to make them reusable across different context.

Adding Custom Parameters To A Computed Field

Let's look at the code below as a sample of how to pass custom parameters to drive reusability.


using System;
using System.Xml;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.ComputedFields;
using Sitecore.Xml;

namespace ParklandLibrary.yrl.code.ComputedFields
{
    public class CustomParameterComputedField : AbstractComputedIndexField
    {
        public string CustomParameter { get; set; }

        public CustomParameterComputedField(XmlNode configNode) : base(configNode)
        {
            this.CustomParameter = XmlUtil.GetAttribute("customerParameter", configNode);            
        }
        public override object ComputeFieldValue(IIndexable indexable)
        {                                    
            return String.Format("We added the custom parameter: {0}", CustomParameter);
        }
    }
}

The key items to note here are:

  • We inherited the abstract class AbstractComputedIndexField which implements the IComputedIndexField interface
  • We use a custom constructor with an XmlNode argument to load the customerParameter value from the config
  • The ComputeFieldValue() method returns its value into the fieldName which is set in AbstractComputedIndexField

Creating A Customizable Date Using A Computed Field

Let's walk-through a complete real world example. We'll make a computed field that outputs a DateField from Sitecore into any format. We'll start with the config.


<field fieldName="_EventStartLongDateTime" toStringFormat="dddd, MMMM d yyyy h:mm tt">GetFishtank.ComputedFields.ComputedDateField</field>
<field fieldName="_EventStartTime" toStringFormat="h:mm tt">GetFishtank.ComputedFields.ComputedDateField,GetFishtank</field>

And here is a complete Computed Field class that uses a toStringFormat.

This time we'll implement the IComputedIndexField ourselves and not use the abstract base class.


using System.Xml;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.ComputedFields;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Xml;

namespace GetFishtank.ComputedFields
{
    public class ComputedDateField : IComputedIndexField
    {
        public string FieldName { get; set; }
        public string ReturnType { get; set; }
        public string ToStringFormat { get; set; }

        public const string SpecialDateField = "Special Date";

        public ComputedDateField(XmlNode configNode)
        {
            this.FieldName = XmlUtil.GetAttribute("fieldName", configNode);
            this.ReturnType = XmlUtil.GetAttribute("returnType", configNode);
            this.ToStringFormat = XmlUtil.GetAttribute("toStringFormat", configNode);            
        }

        public virtual object ComputeFieldValue(IIndexable indexable)
        {                    
            Item item = (Item)(indexable as SitecoreIndexableItem);
            if (item == null)
                return (object)null;

            var itemField = item.Fields[SpecialDateField];
            if (itemField == null) return null;

            var dateField = (DateField) itemField;
            
            return (object) dateField.DateTime.ToString(ToStringFormat);            
        }        
    }
}

In this specific case, we're rending dates on the client-side in a number of views. Depending on the view, we want to display the date information in different ways. It makes sense to handle the date transforms once with an extensible computed field instead repeated JavaScript date formatting.

This outputs of "Sunday, December 11 2016 4:00 PM" and "4:00 PM" respectively.

And of course there are better, more-powerful use-cases than what I've laid out above. Thanks for reading.

Fish