Posted in: Comments

Lets say you want to give your editors the possibility to select a user (username) in a property so we can display e.g. a byline in an article. The simple solution is to just add a string property to your page type, but then the editor need to enter the username manually. Instead we can use the AutoSuggestSelection attribute, then we only need to implement an ISelectionQuery.

Fortunately there is an API in Episerver we can use to query for users, IQueryableNotificationUsers, but keep in mind that the API is internal and may change without notice.

First we need to implement our query:

namespace DV
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using EPiServer.Notification;
    using EPiServer.ServiceLocation;
    using EPiServer.Shell.ObjectEditing;

    [ServiceConfiguration(typeof(ISelectionQuery))]
    public class UserSelectionQuery : ISelectionQuery
    {
        private readonly IQueryableNotificationUsers userRepository;

        public UserSelectionQuery(IQueryableNotificationUsers userRepository)
        {
            this.userRepository = userRepository;
        }

        public ISelectItem GetItemByValue(string value)
        {
            var task = Task.Run(async () => await this.userRepository.FindAsync(value, 0, 1));

            task.Wait();

            if (task.Result.TotalCount == 0)
            {
                return null;
            }

            var user = task.Result.PagedResult.Single();

            return new SelectItem
            {
                Text = $"{user.DisplayName} ({user.UserName})",
                Value = user.UserName
            };
        }

        public IEnumerable<ISelectItem> GetItems(string query)
        {
            var task = Task.Run(async () => await this.userRepository.FindAsync(query, 0, 10));

            task.Wait();

            if (task.Result.TotalCount == 0)
            {
                return Enumerable.Empty<ISelectItem>();
            }

            return task.Result.PagedResult.Select(user => new SelectItem
            {
                Text = $"{user.DisplayName} ({user.UserName})",
                Value = user.UserName
            });
        }
    }
}

Then we can use it in the attribute:

[AutoSuggestSelection(typeof(UserSelectionQuery))]
[Display(Name = "Published by")]
public virtual string PublishedBy { get; set; }

Hope this helps.