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 Per
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
}
}
You can simply use Razor syntax:
@Html.DropDownList("StudentGender",
Html.GetEnumSelectList<Gender>(),
"Select Gender",new { @class = "form-control" })
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" })
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 <enum-radio-button> 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);
}
}
}
}
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>()
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