112

I'm trying to create a dropdown list with an enum property in ASP.NET MVC Core using the tag helper in a Razor view:

Here is the model:

public class PersonalMember : Member
{
    [Required, Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required, Display(Name = "Last Name")]
    public string LastName { get; set; }

    [EnumDataType(typeof(Gender))]
    public Gender GenderType { get; set; }
}

public enum Gender
{
    Male = 1,
    Female = 2
}

Here is part of a form in the view:

<div class="form-group">
    <label asp-for="GenderType" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <select asp-for="GenderType" asp-items="Html.GetEnumSelectList<GenderType>()">
            <option selected="selected" value="">Please select</option>
        </select>
        <span asp-validation-for="GenderType" class="text-danger" />
    </div>
</div>

The problem I'm having is that after Html.GetEnumSelectList, GenderType is not recognized and shows up as an error.

Does anyone know how to solve this?

1
  • 2
    try to specify it like... @(Html.GetEnumSelectList<GenderType>())"
    – K D
    Commented Jan 19, 2017 at 11:32

9 Answers 9

180

I think you accidentally used GenderType instead of Gender. The correct syntax is

<select asp-for="GenderType" asp-items="Html.GetEnumSelectList<Gender>()">
    <option selected="selected" value="">Please select</option>
</select>
3
  • 11
    This should be the answer, it uses the modern tag helpers AND shows you how to implement the GetEnumSelectList<Enum>() to build the list item. Commented May 16, 2019 at 19:16
  • First suggestion that worked for me in .net core thanks Commented Sep 19, 2020 at 16:33
  • 1
    Is there no @Html.EnumDropdownFor method that can do this in one line?
    – jjxtra
    Commented Mar 14, 2021 at 20:53
72

GenderType is your property name, not the Enum type. The GetEnumSelectList method expects you to give it the type of the Enumeration, not the name of the property in your model.

Try this:

Html.GetEnumSelectList<Gender>()
5
  • Might need to mark it as metadata in the asp-for like: Html.GetEnumSelectList<GenderType.Meta.Gender>().. The OP didn´t mark which version of the MVC-framework is used Commented Jan 19, 2017 at 11:47
  • I've tried Html.GetEnumSelectList<Gender>() and Html.GetEnumSelectList<enum Gender>() - they both show up as errors Commented Jan 19, 2017 at 19:50
  • 1
    what error do you get when you use my example above? The same one? I don't think your second example is valid syntax
    – ADyson
    Commented Jan 20, 2017 at 9:40
  • 10
    In razor, you need to surround by ( ): @(Html.GetEnumSelectList<Gender>()); Because razor interprets the < > as html tags otherwise
    – dyesdyes
    Commented Dec 14, 2017 at 13:53
  • @ADyson could you see this please? stackoverflow.com/questions/48094102/…
    – user9046719
    Commented Jan 4, 2018 at 15:00
36

You can simply use Razor syntax:

@Html.DropDownList("StudentGender", 
    Html.GetEnumSelectList<Gender>(),
    "Select Gender",new { @class = "form-control" })
1
  • 1
    This is indeed what we need!
    – juFo
    Commented Oct 15, 2018 at 14:34
11

The below was what worked for me. This is necessary and the way it is because the enum itself is a class declared under the scope of the class which you are using as a model.

<select asp-for="Status" class="form-control" asp-items="@Html.GetEnumSelectList<Cart.CartStatus>()"></select>

below my model (work in progress) for reference

 public class Cart
    {
        public int CartId { get; set; }
        public List<Order> Orders { get; set; }
        [Required]
        public string UserId { get; set; }
        public DateTime DeliveryDate { get; set; }
        public CartStatus Status { get; set; }
        public enum CartStatus
        {
            Open = 1,
            Confirmed = 2,
            Shipped = 3,
            Received = 4
        }
    }
8

I got the same problem, I burned my head looking for a solution!

You can solve this situation, instantiating you model on top of your view like:

@using CRM.Model;

@using YourSolution.Model

Yes, it sounds too strange but belive me, it works! See my answer on my own post.

Select ENUM Tag Helper in ASP.NET Core MVC

7

There needs one case for editing case when there is selected option in DropDownList

Using enums with the ASP.NET 5 (MVC 6) Select TagHelper

public enum Gender {
  [Display(Name = "Male")]Male = 1,
  [Display(Name = "Female N")]Female = 2,
  [Display(Name = "Other")]Other = 3 
}

**For Editing Case:

@Html.DropDownListFor(m => m, Html.GetEnumSelectList(typeof(Gender)))
@Html.DropDownListFor(m => m.Gender, Html.GetEnumSelectList<Gender>()))

@Html.DropDownListFor(m => m.Gender, Html.GetEnumSelectList<Gender>(), "Select", new { @class = "form-control" })

**For Normal Case:

<select asp-for="Gender" asp-items="@Html.GetEnumSelectList<Gender>()">
   <option selected="selected" value="">Please select</option>
</select>

<select asp-for="Gender" asp-items="ViewBag.Genders"></select>

@Html.DropDownList("Gender", Html.GetEnumSelectList<Gender>(), "Select", new { @class = "form-control" })
0
2

you use Gender to asp-items="Html.GetEnumSelectList -GenderType- ()" instead of GenderType

such as asp-items="Html.GetEnumSelectList -Gender- ()"

0

This is the way to implement Custom TagHelper DropDownList with enum in netcore 3

 <radio-button-enum asp-for="@Model.Status" value="@Model.Status"></radio-button-enum>


/// <summary>
/// <see cref="ITagHelper"/> implementation targeting &lt;enum-radio-button&gt; elements with an <c>asp-for</c> attribute, <c>value</c> attribute.
/// </summary>
[HtmlTargetElement("radio-button-enum", Attributes = RadioButtonEnumForAttributeName)]
public class RadioButtonEnumTagHelper : TagHelper
{
    private const string RadioButtonEnumForAttributeName = "asp-for";
    private const string RadioButtonEnumValueAttributeName = "value";

    /// <summary>
    /// Creates a new <see cref="RadioButtonEnumTagHelper"/>.
    /// </summary>
    /// <param name="generator">The <see cref="IHtmlGenerator"/>.</param>
    public RadioButtonEnumTagHelper(IHtmlGenerator generator)
    {
        Generator = generator;
    }

    /// <inheritdoc />
    public override int Order => -1000;

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    protected IHtmlGenerator Generator { get; }

    /// <summary>
    /// An expression to be evaluated against the current model.
    /// </summary>
    [HtmlAttributeName(RadioButtonEnumForAttributeName)]
    public ModelExpression For { get; set; }

    [HtmlAttributeName(RadioButtonEnumValueAttributeName)]
    public Enum Value { get; set; }

    /// <inheritdoc />
    /// <remarks>Does nothing if <see cref="For"/> is <c>null</c>.</remarks>
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (output == null)
        {
            throw new ArgumentNullException(nameof(output));
        }

        var childContent = await output.GetChildContentAsync().ConfigureAwait(true);
        string innerContent = childContent.GetContent();
        output.Content.AppendHtml(innerContent);

        output.TagName = "div";
        output.TagMode = TagMode.StartTagAndEndTag;
        output.Attributes.Add("class", "btn-group btn-group-radio");
        
        var modelExplorer = For?.ModelExplorer;
        var metaData = For?.Metadata;

        if (metaData?.EnumNamesAndValues != null)
        {
            foreach (var item in metaData.EnumNamesAndValues)
            {
                string enumId = $"{metaData.ContainerType.Name}_{metaData.PropertyName}_{item.Key}";
                string enumInputLabelName = item.Key.ToString();

                bool enumIsChecked = false;
                if (Value != null)
                {
                    if (enumInputLabelName == Value.ToString())
                    {
                        enumIsChecked = true; }
                }
                else
                {
                    if (For.Model != null && enumInputLabelName == For.Model.ToString())
                    {
                        enumIsChecked = true;
                    }
                }

                var enumResourcedName = metaData.EnumGroupedDisplayNamesAndValues.FirstOrDefault(x => x.Value == item.Value);
                if (enumResourcedName.Value != null)
                {
                    enumInputLabelName = enumResourcedName.Key.Name;
                }

                var enumRadio = Generator.GenerateRadioButton(
                    ViewContext,
                    For.ModelExplorer,
                    metaData.PropertyName,
                    item.Key,
                    false,
                    htmlAttributes: new { @id = enumId });
                enumRadio.Attributes.Remove("checked");
                if (enumIsChecked)
                {
                    enumRadio.MergeAttribute("checked", "checked");
                }
                output.Content.AppendHtml(enumRadio);

                var enumLabel = Generator.GenerateLabel(
                    ViewContext,
                    For.ModelExplorer,
                    For.Name,
                    enumInputLabelName,
                    htmlAttributes: new { @for = enumId, @Class = "btn btn-default" });
                output.Content.AppendHtml(enumLabel);
            }
        }
    }
}
0
  • First Create a Custom HTML Helper:

    namespace Infrastructure;

    public static class HtmlHelpers : object { static HtmlHelpers() { }

      public static Microsoft.AspNetCore.Mvc.Rendering.SelectList DtatGetEnumSelectList<TEnum>
          (this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper html, int? selectedValue = null) where TEnum : struct
      {
          var list = html.GetEnumSelectList<TEnum>().ToList();
    
          var emptySelectListItem =
              new Microsoft.AspNetCore.Mvc.Rendering
              .SelectListItem(text: "Select an item", value: string.Empty);
    
          list.Insert(index: 0, item: emptySelectListItem);
    
          var result =
              new Microsoft.AspNetCore.Mvc.Rendering
              .SelectList(items: list, selectedValue: selectedValue,
              dataTextField: nameof(Microsoft.AspNetCore.Mvc.Rendering.SelectListItem.Text),
              dataValueField: nameof(Microsoft.AspNetCore.Mvc.Rendering.SelectListItem.Value));
    
          return result;
      }
    

    }

  • Second use this custom html helper in your razor page:

select asp-for="ViewModel.Gender" asp-items="@(Html.DtatGetEnumSelectList<Domain.Enums.Gender>(selectedValue: (int)Model.ViewModel.Gender))"

Not the answer you're looking for? Browse other questions tagged or ask your own question.