Monday, October 9, 2017

Custom Property In EPiServer And EPiFInd Indexing

In one of our project we had to build the autosuggest property. However, the default type of autosuggest property is string but we wanted to store custom object so we can index through EPiFind with additional values.

Therefore, we implemented custom class to store additional values and also needed JsonConverter for 2 reasons

  1. Convert Class to String for Dojo Framework so existing autosuggest property works as expected
  2. Convert and index object for EPiFind differently
We will delimte the value of autosuggest property with '-' to break it into multiple property and save it and index it properly.

Define the property


[BackingType(typeof(PropertyTag))]
[Display(Order = 45, Description = "Select competition to filter the contents of the page")]
[AutoSuggestSelection(typeof(TagSelectionQuery), AllowCustomValues = false)]
public virtual Tag Competition { get; set; }


Define the PropertyTag Class



    [PropertyDefinitionTypePlugIn(Description = "A property to tag content", DisplayName = "Tag")]
    [JsonConverter(typeof(TagJsonConverter))]
    public class PropertyTag : PropertyLongString
    {
        public override PropertyDataType Type => PropertyDataType.LongString;

        public override Type PropertyValueType => typeof(Tag);

        public override object Value
        {
            get { return Tag.Parse(base.Value?.ToString()); }
            set { base.Value = value?.ToString(); }
        }

        public override object SaveData(PropertyDataCollection properties)
        {
            return this.LongString;
        }
    }


Define the JsonConverter



 internal class TagJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.Value is Tag tag)
                return tag;

            return new Tag(reader.Value.ToString());
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }

            if (writer is MaxDepthJsonWriter && value is Tag tag)
            {
                writer.WriteStartObject();
                writer.WritePropertyName($"Text{TypeSuffix.String}");
                writer.WriteValue(tag.Text);
                writer.WritePropertyName($"Value{TypeSuffix.String}");
                writer.WriteValue(tag.Value);
                writer.WriteEndObject();
                return;
            }

            if (value is Tag itag)
            {
                writer.WriteValue(itag.ToString());
            }
            else
            {
                writer.WriteValue(value.ToString());
            }
        }
    }


Define Tag Class




 [JsonConverter(typeof(TagJsonConverter))]
    public class Tag
    {
        private string text;
        private string value;
        private string tag;
        private bool isLoaded;

        public string Text
        {
            get
            {
                if (!isLoaded)
                    Load();

                return text;
            }

            set
            {
                text = value;
            }
        }

        public string Value
        {
            get
            {
                if (!isLoaded)
                    Load();

                return value;
            }

            set
            {
                this.value = value;
            }
        }

        public Tag()
        { }

        public Tag(string tag)
        {
            this.tag = tag;
        }

        public Tag(string value, string text)
        {
            isLoaded = true;
            this.value = value;
            this.text = text;
        }

        public string GetId(string type) => Value?.Substring(type.Length);

        public override string ToString()
        {
            return $"{Value}{ "-" }{Text}";
        }

        private void Load()
        {
            isLoaded = true;
            if (!string.IsNullOrWhiteSpace(tag))
            {
                var parts = tag.Split(new[] { "-" }, 2);
                if (parts.Length == 1)
                {
                    text = parts[0];
                    value = string.Empty;
                }
                else
                {
                    value = parts[0];
                    text = parts[1];
                }
            }
        }

        public static Tag Parse(string tag)
        {
            return string.IsNullOrWhiteSpace(tag) ? null : new Tag(tag);
        }
    }

Define TagSelectionQuery


    [ServiceConfiguration(typeof(ISelectionQuery))]
    public class TagSelectionQuery : ISelectionQuery
    {
        private const int Depth = 0;

        protected virtual string Prefix { get; } = Constants.Tags.Competition;

        public IEnumerable GetItems(string query)
        {
            /* Return List Of Select Items With Value Delimited by '-' For value and text of tag
        }

        ///         /// Will be called when initializing an editor with an existing value to get the corresponding text representation.
        ///         public ISelectItem GetItemByValue(string value) => /* Return SelectItem */;
    }


Pro Tip: Make Sure Admin For Property Looks Like below

No comments:

Post a Comment