Published on, Time to read
🕒 2 min read

Optimizely / Episerver: How to get current content in ISelectionFactory?

Optimizely / Episerver: How to get current content in ISelectionFactory?

Introduction

Selection factories are used to populate dropdowns in the Episerver UI. It is used when either SelectOne or SelectMany attributes are used on a property.

The selection factory is a class that implements ISelectionFactory interface. It has a following signature:

public interface ISelectionFactory
{
    IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata);
}

The problem is that there is no simple way to get the current object that is being edited. The ExtendedMetadata object does not contain any information about the current object. The FindOwnerContent() returns null.

Solution

The solution is to get the content ID from the HTTP request header. It is stored in the x-epicurrentcontentcontext header. The following code snippet shows how to get the content ID:

public virtual IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
{
    var currentContext = _httpContextAccessor.HttpContext?.Request.Headers["x-epicurrentcontentcontext"];
    if (currentContext is null) return Enumerable.Empty<ISelectItem>();

    var elementId = currentContext.Value.FirstOrDefault();
    if (elementId is null) return Enumerable.Empty<ISelectItem>();

    var get = _contentLoader.TryGet(new ContentReference(elementId), out ElementBlockBase? currentBlock);

    // remaining logic here
}

Where _httpContextAccessor is an instance of IHttpContextAccessor that is injected into the constructor.

Conclusion

This is a simple solution to a problem that I struggled with for a while. The remarks are:

There's only one Google hit for the x-epicurrentcontentcontext header. It is a forum post from 2016. Thus, it would be nice that such scenario would be documented.

Please note the solution won't be working in the quick edit dialog. As per above forum post:

This however will not work in the quick-edit dialog, the x-epicurrentcontentcontext header will there instead contain whatever content you were on before opening the quick-edit dialog.

External links