How to use a datatype to populate a dropdown list in Umbraco v8

Posted written by Paul Seal on July 01, 2020 Umbraco

In this post I share the code I wrote to get the values from dropdowns and it can be used for checkbox lists and radio button lists too.

Some background

Recently I was asked to build a membership registration and login flow for a client. The client was Tarik from Creativaholic Studio. Tarik has kindly agreed for me to share some of the code I wrote for this, as it solves some interesting problems I encountered along the way.

In this project, I needed to have properties on the member profile which used the dropdown list, checkbox list and radio button list datatypes.

And I needed to be able to edit them in the edit profile screen.

So what I had to do was get the values from the dropdown datatype in the backoffice and use them to load an Html.DropdownList in the form on the front end.

Dropdown data type

1

In order to get the values from the datatype I decided to put the code in a service to make it reusable and allow it to be used with dependency injection.

I created a service called DataTypeValueService.

IDataTypeValueService Interface

First I created an interface for it:

using System.Collections.Generic;
using System.Web.Mvc;

namespace CodeShare.Core.Services
{
    public interface IDataTypeValueService
    {
        IEnumerable<SelectListItem> GetItemsFromValueListDataType(string dataTypeName, string[] selectedValues);
    }
}

DataTypeValueService Class

Next I created the implementation for the interface:

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;

namespace CodeShare.Core.Services
{
    public class DataTypeValueService : IDataTypeValueService
    {
        private readonly IDataTypeService _dataTypeService;

        public DataTypeValueService(IDataTypeService dataTypeService)
        {
            _dataTypeService = dataTypeService;
        }

        public IEnumerable<SelectListItem> GetItemsFromValueListDataType(string dataTypeName, string[] selectedValues)
        {
            IEnumerable<SelectListItem> items = null;

            var dataTypeConfig =
                (ValueListConfiguration)_dataTypeService.GetDataType(dataTypeName).Configuration;


            if (dataTypeConfig?.Items != null &amp;&amp; dataTypeConfig.Items.Any())
            {
                items =
                    dataTypeConfig.Items.Select(x => new SelectListItem()
                    {
                        Text = x.Value,
                        Value = x.Value,
                        Selected = selectedValues != null &amp;&amp; selectedValues.Contains(x.Value)
                    });
            }

            return items;
        }
    }
}

Now we have a method where we can get the options from the data type as an IEnumerable of SelectListItem. The good thing about using this as a result set is that each item can have Text, Value and Selected properties.

View Model

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace CodeShare.Core.Models.ViewModels
{
    public class EditProfileViewModel
    {
        [Display(Name = "Job Title")]
        public string JobTitle { get; set; }

        public IEnumerable<SelectListItem> JobTitleOptions { get; set; }
    }
}

We can now call this code from our controller to load the values into our JobTitleOptions property on our view model.

Register the service for Dependency Injection usage

using CodeShare.Core.Services;
using Umbraco.Core;
using Umbraco.Core.Composing;

namespace CodeShare.Core.Composing
{
    [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
    public class RegisterServicesComposer : IUserComposer
    {
        public void Compose(Composition composition)
        {
            composition.Register(typeof(IDataTypeValueService),
                typeof(DataTypeValueService), Lifetime.Request);
        }
    }
}

Controller with Dependency Injection

using CodeShare.Core.Models.ViewModels;
using CodeShare.Core.Services;
using System.Web.Mvc;
using Umbraco.Web.Mvc;

namespace CodeShare.Core.Controllers.Surface
{
    public class AccountSurfaceController : SurfaceController
    {
        private readonly IDataTypeValueService _dataTypeValueService;

        public AccountSurfaceController(IDataTypeValueService dataTypeValueService)
        {
            _dataTypeValueService = dataTypeValueService;
        }

        [HttpGet]
        public ActionResult RenderEditProfile()
        {
            var model = new EditProfileViewModel();

            model.JobTitleOptions =
                _dataTypeValueService.GetItemsFromValueListDataType("[Dropdown] Job Titles", selectedValues: null);

            return PartialView("~/Views/Partials/Membership/_EditProfile.cshtml", model);
        }
    }
}

Using this in the Html.DropDownList

@Html.DropDownListFor(x => x.JobTitle, Model.JobTitleOptions, "Please select..")

This will now load the dropdown for you on the front end.

If you need help with the implementation of this, you can get in touch with me on LinkedIn