A critical vulnerability was discovered in React Server Components (Next.js). Our systems remain protected but we advise to update packages to newest version. Learn More

Manoj Kumawat
Jun 26, 2019
  5420
(5 votes)

Using ExtendedMetadata from SelectionFactory

Prerequisite - 

This tutorial requires a knowledge of ISelectionFactory.

In this tutorial I would like to share my experience with SelectionFactory features from Episerver.

We had a requirement where an Episerver CMS user should be able to view the options based on certain parameters. Consider the case where you have a multiple options type fields within the CMS those should be fetching their values according to input parameters via attribute. 

Step 1 - Creating an abstract SelectionFactory class

We are going to inherit the Interface ISelectionFactory from EPiServer.Shell.ObjectEditing Assembly and creating our custom LookupSelectionFactory as a service factory.

I would have an additional method AddItems of type virtual to be able to override in derived class (the class which inherits LookupSelectionFactory).

Note that It has two parameteres and one of them is ExtendedMetadata that we are going to use to fetch the values from attribute.

public abstract class LookupSelectionFactory : ISelectionFactory
{
   protected virtual IEnumerable<ISelectItem> AddItems(RestClient client, ExtendedMetadata metadata)
   {
    throw new NotImplementedException();
   }
}

Step 2 - Creating an Attribute class (to input desired parameters)

[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
public class PickListAttribute : System.Attribute
{
	public string AttributeName { get; set; }
	public string AttributeType { get; set; }
}

AttributeTargets.All - Specifies that Attribute can be applied to any application element. Whether it's a constructor, class, delegate, event etc.

AllowMultiple - Gets or sets a Boolean value indicating whether more than once instance of the indicated attribute can be specified for a single program element.

Inhertied - Gets or sets a Boolean value that determines whether the indicated attribute is inherited by derived class and overriding members.

Step 3 - Using factory on Block property

[CultureSpecific]
        [Display(
            Name = "Title Options", Description = "Title Options", GroupName = FormTabGroups.ABOUT_YOU_TAB, Order = 1)]
        [PickListAttribute(AttributeType = "CONTACT", AttributeName = "TITLE")]
        [SelectMany(SelectionFactoryType = typeof(ShowOptionsSelectionFactory))]
        public virtual string TitleOptions { get; set; }

In the next step > create ShowOptionsSelectionFactory that will display the Options in Episerver.

Step 4 - Inheriting abstract factory and reusing it in custom selection factory for our purpose

 public class ShowOptionsSelectionFactory : LookupSelectionFactory
        {
            protected override IEnumerable<ISelectItem> AddItems(RestClient client, ExtendedMetadata metadata)
            {
                List<ISelectItem> items = new List<ISelectItem>();
                try
                {
                    PickListAttribute pickListAttribute = (PickListAttribute)metadata.Attributes.FirstOrDefault(c => c is PickListAttribute);
                    string name = pickListAttribute.AttributeName;
                    string type = pickListAttribute.AttributeType;

                  items.Add(new SelectItem()
                   {
                     Value = type,
                     Text = name,
                   });
                }
                catch (Exception ex)
                {
                    //catch the exception here
                }

                return items;

            }
        }

The line above picks the attribute of type PickListAttribute amongst other Attributes on the same property - [CultureSpecific], [Display], [SelectMany] with the help of metadata parameter.

(PickListAttribute)metadata.Attributes.FirstOrDefault(c => c is PickListAttribute) 

The metadata keeps the Attributes information along with it that you can pull based on your needs.

For instance if you want to fetch the values for Display attribute being used on the property TitleOptions, Then you can query within Attributes property from metadata and cast it like this - 

DisplayAttribute crmPickListAttribute = (DisplayAttribute)metadata.Attributes.FirstOrDefault(c => c is DisplayAttribute);

Enjoy your day!

Jun 26, 2019

Comments

Please login to comment.
Latest blogs
Building simple Opal tools for product search and content creation

Optimizely Opal tools make it easy for AI agents to call your APIs – in this post we’ll build a small ASP.NET host that exposes two of them: one fo...

Pär Wissmark | Dec 13, 2025 |

CMS Audiences - check all usage

Sometimes you want to check if an Audience from your CMS (former Visitor Group) has been used by which page(and which version of that page) Then yo...

Tuan Anh Hoang | Dec 12, 2025

Data Imports in Optimizely: Part 2 - Query data efficiently

One of the more time consuming parts of an import is looking up data to update. Naively, it is possible to use the PageCriteriaQueryService to quer...

Matt FitzGerald-Chamberlain | Dec 11, 2025 |

Beginner's Guide for Optimizely Backend Developers

Developing with Optimizely (formerly Episerver) requires more than just technical know‑how. It’s about respecting the editor’s perspective, ensurin...

MilosR | Dec 10, 2025