Displaying enum Display Name when iterating over enum values in Razor page (in ASP.NET Core)

2.9k views Asked by At

How do you display the Display name for an enum when you're iterating over the enum values on a Razor Page (in ASP.NET Core)?

Razor Page:

<label asp-for="Survey.ToldNotToTakeHormones"></label><br />
@foreach (var answer in Enum.GetValues(typeof(AnswerYND)))
{
    <div class="custom-control custom-radio custom-control-inline ">
        <label><input type="radio" asp-for="Survey.ToldNotToTakeHormones" value="@answer" />@answer</label>
    </div>
}

Code behind razor page:

public class EditModel : PageModel
{
    [BindProperty]
    public Survey Survey { get; set; }

Survey class:

public class Survey
{
    [Display(Name = "Have you ever been told by a medical professional not to take hormones?")]
    public AnswerYND? ToldNotToTakeHormones { get; set; }

AnswerYND:

public enum AnswerYND
{ 
    Yes,
    No,
    [Display(Name="Don't Know")]
    DontKnow
}
2

There are 2 answers

0
Dan On BEST ANSWER

So, I was able to utilize Description instead of Display Name and achieved the desired effect.
I had to create the following extension method:

public static class EnumHelper
{
    public static string GetDescription<T>(this T enumValue)
        where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
            return null;

        var description = enumValue.ToString();
        var fieldInfo = enumValue.GetType().GetField(enumValue.ToString());

        if (fieldInfo != null)
        {
            var attrs = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), true);
            if (attrs != null && attrs.Length > 0)
            {
                description = ((DescriptionAttribute)attrs[0]).Description;
            }
        }

        return description;
    }
}

And then I was able to access the extension method in the Razor page by casting the result of Enum.GetValues(typeof(AnswerYND)):

<label asp-for="Survey.CurrenltyUsingBirthControl"></label><br />
@foreach (var answer in Enum.GetValues(typeof(AnswerYND)).Cast<AnswerYND>())
{
    <div class="custom-control custom-radio custom-control-inline ">
    <label><input type="radio" asp-for="Survey.CurrenltyUsingBirthControl" value="@answer" />@answer.GetDescription()</label>
    </div>
 }
0
Nate W On

There are better ways to go about creating what you are looking for, if you're interested in binding enums to controls or fields, and having the system display the name of the enum, rather than the underlying value. The important thing that makes this complicated is that under the hood, the system isn't handling an enum as a string that gets picked from the developer-defined list; rather, it's handled by default as an Int32.

I found some other answers on Stack Overflow that might help you to see some better possible solutions. This answer explains how you can create your own type-safe class that handles like an enum, but returns the string value that you're looking for. This answer is possibly a duplicate of the same question, but adds more perspectives to the topic. I used code samples from the first question to help you see that what you're looking for can be found, but might not be simple.

public class Survey
{
    [Display(Name = "Have you ever been told by a medical professional not to take hormones?")]
    public AnswerYND? ToldNotToTakeHormones { get; set; }
}

public enum AnswerYND
{
    Yes = 1,
    No = 2,
    [Display(Name = "Don't Know")]
    DontKnow = 3
}

class Program
{
    static void Main(string[] args)
    {
        var survey = new Survey();
        Console.WriteLine(survey);
        var options = Enum.GetValues(typeof(AnswerYND));
        for (int i = 0; i < options.Length; i++)
        {
            Console.WriteLine($"Option {i + 1}: {options.GetValue(i)}");
        }
        var choice = Console.ReadLine();
        if (int.TryParse(choice, out int intChoice) && Enum.IsDefined(typeof(AnswerYND), intChoice))
        {
            AnswerYND enumChoice = (AnswerYND)intChoice;
            var name = (enumChoice
                .GetType()
                .GetField(enumChoice.ToString())
                .GetCustomAttributes(typeof(DisplayAttribute), false)
                as DisplayAttribute[])
                .FirstOrDefault()?
                .Name;
            Console.WriteLine($"You selected: {name}");
        }
    }