Restricting Episerver Commerce media groups via a dropdown

When assigning groups to media assets in Episerver Commerce the editor has to enter them as text, this means there is always the potential for typos when assigning groups and the available options aren't apparent—often necessitating consulting the editor guide and some copy-paste.

In many scenarios it'd be much more convenient just to pick the group from a dropdown, which is the subject of this blog post. The old idiom states that "a picture is worth a thousand words", so hopefully this animated GIF summarizes what we're trying to achieve:

Selecting a group in Episerver Commerce via a dropdown

I realize that this has, to some degree, been done before. The approach taken in this blog post, however, doesn't require a custom Dojo widget, which means it is (at least, in my opinion) more easily modifiable or extensible. Here, for example, I use a SelectOne attribute but there's no reason it couldn't easily swapped out to an auto-suggestion editor or maybe even a SelectMany attribute (other than the fact I haven't tested those).

Right, enough waffle, let's see some code.

The key to this approach is creating a new custom media model inheriting CommerceMediaModel (EPiServer.Commerce.Shell.ObjectEditing.InternalMetadata). We can then add our GroupName property (with a new modifier) and specify a selection factory:

public class CustomCommerceMediaModel : CommerceMediaModel
{
    [Required]
    [SelectOne(SelectionFactoryType = typeof(CommerceMediaGroupSelectionFactory))]
    public new string GroupName { get; set; }
}

That's all it needs.

The selection factory can be whatever you like at this point, here's a very simple example:

public class CommerceMediaGroupSelectionFactory : ISelectionFactory
{
    public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
    {
        var options = new List<SelectItem>
        {
            new SelectItem {Text = "Default", Value = "default"},
            new SelectItem {Text = "Primary ", Value = "primary" },
            new SelectItem {Text = "Packshot ", Value = "packshot" },
            new SelectItem {Text = "Video", Value = "video" }
        };

        metadata.InitialValue = options.First();

        return options;
    }
}

Finally, we just need an EditorDescriptor which fires after the default one has already set everything up (hence the EditorDescriptorBehavior.PlaceLast) and switches the model to our custom one:

[EditorDescriptorRegistration(TargetType = typeof(ItemCollection<CommerceMedia>), UIHint = SystemUiHint.CommerceMediaCollection,
    EditorDescriptorBehavior = EditorDescriptorBehavior.PlaceLast)]
public class CustomCommerceMediaCollectionEditorDescriptor : EditorDescriptor
{
    public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
    {
        metadata.EditorConfiguration["itemType"] = typeof(CustomCommerceMediaModel).FullName;
    }
}

Not many lines of code huh? And, if you don't count the selection factory it's hardly anything at all. As I said, I like how potentially extensible this approach is where you're not necessarily limited to using a dropdown.

Anyway, that's it, so hopefully it's useful!

Comments

Really nice. Thank you for the share

Marcus Babajews