Udemy

Bind Enum to DropdownList in asp.net mvc

Friday, March 27, 2015 2 Comments A+ a-

Introduction:

 
Sometimes we have scenario while development where we need to populate dropdownlist from Enum. There are a couple of ways to do it. But every way has it's pros and cons. One should always keep in mind the SOLID and DRY principle while writing code. I will show two ways to do it and you will be able to understand which one is better and why it is better.

Approach 1 (Typical Way):

The first approach in my point of view is not very elegant but it will surely do what we want it to.

Consider following Enum which we want to populate in the drop down:

 public enum eUserRole : int
 {
    SuperAdmin = 0,
    PhoenixAdmin = 1,
    OfficeAdmin = 2,
    ReportUser = 3,
    BillingUser = 4
  }

So normally what we do is create SelectList by adding each Enum value following way in the action:

  var enumData = from eUserRole e in Enum.GetValues(typeof(eUserRole))
                 select new 
                      { 
                        ID = (int)e, 
                        Name = e.ToString() 
                      };
 
Now set it in ViewBag so that we can use it in View:

  ViewBag.EnumList = new SelectList(enumData,"ID","Name");

and Now in View:

  @Html.DropDownList("EnumDropDown",ViewBag.EnumList as SelectList)

Problem in Approach 1:

The problem with the above way is that whenever we have Enum to be binded with some Html Helper we have to write the above linq query code to get the enum all values in the action which is a bit pain to rewrite one thing again and again.We will see next how we can make it better and reusable.

Approach 2:

Now here is an elegant way to achieve it using Extension Method and Generics, which will return us Enum values as a SelectList for any type of Enum:

public static class ExtensionMethods
{
     public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum obj)
         where TEnum : struct, IComparable, IFormattable, IConvertible 
     {

     return new SelectList(Enum.GetValues(typeof(TEnum)).OfType<Enum>()
         .Select(x =>
             new SelectListItem
             {
                 Text = Enum.GetName(typeof(TEnum), x),
                 Value = (Convert.ToInt32(x)).ToString()
             }), "Value", "Text");

     }
 }

and now we just need to call it on any Enum in action  this way:

  ViewBag.EnumList = eUserRole.SuperAdmin.ToSelectList();

we can also use it directly in the View, just we have to include namespace in case it's in seperate namespace:

  @Html.DropDownList("EnumDropDown",eUserRole.SuperAdmin.ToSelectList())

You will probably need to set selected value of dropdownlist in the case when user is editing record.

We can extend the extension method according to our requirents.

Overload with Selected Value parameter:

Here is the extension method overload to pass selected value in case we want to set selected value, you can write other overloads as well according to the need:

public static class ExtensionMethods
{
    public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum obj,object selectedValue)
  where TEnum : struct, IComparable, IFormattable, IConvertible 
    {

    return new SelectList(Enum.GetValues(typeof(TEnum)).OfType<Enum>()
        .Select(x =>
            new SelectListItem
            {
                Text = Enum.GetName(typeof(TEnum), x),
                Value = (Convert.ToInt32(x)).ToString()
            }), "Value", "Text",selectedValue);

    }
}

and usage in View this way:

  @Html.DropDownList("EnumDropDownWithSelected",eUserRole.SuperAdmin.ToSelectList((int)eUserRole.OfficeAdmin))


Now the drop down will have OfficeAdmin selected by default.


In most of cases we don't want to show Enum value I'm dropdown list instead of that we want to show user friendly term as dropdown text, for that  purpose we can write our Attribute for Enum following way:

Create a custom class which inherits from Attribute type:

 public class EnumDisplayNameAttribute : Attribute
 {
    private string _displayName;
    public string DisplayName
    {
       get { return _displayName; }
       set { _displayName = value; }
    }
  }

and Now use attribute on Enum :

 public enum eUserRole : int
 {
    [EnumDisplayName(DisplayName="Super Admin")]
    SuperAdmin = 0,
    [EnumDisplayName(DisplayName = "Phoenix Admin")]
    PhoenixAdmin = 1,
    [EnumDisplayName(DisplayName = "Office Admin")]
    OfficeAdmin = 2,
    [EnumDisplayName(DisplayName = "Report User")]
    ReportUser = 3,
    [EnumDisplayName(DisplayName = "Billing User")]
    BillingUser = 4
 }


 Now we will need to modify or write another extension method as now we need to pick value of DisplayName attribute.

We now have to extension methods now, one which return specific Enum value DisplayName Attribute value and second which return SelectList against for Enum:

public static class ExtensionMethods
{
    public static System.Web.Mvc.SelectList ToSelectList<TEnum>(this TEnum obj)
        where TEnum : struct, IComparable, IFormattable, IConvertible // correct one
    {

    return new SelectList(Enum.GetValues(typeof(TEnum)).OfType<Enum>()
        .Select(x =>
            new SelectListItem
            {
                Text = x.DisplayName(),
                Value = (Convert.ToInt32(x)).ToString()
            }), "Value", "Text");

    }


   public static string DisplayName(this Enum value)
   {
       FieldInfo field = value.GetType().GetField(value.ToString());

       EnumDisplayNameAttribute attribute
               = Attribute.GetCustomAttribute(field, typeof(EnumDisplayNameAttribute))
                   as EnumDisplayNameAttribute;

       return attribute == null ? value.ToString() : attribute.DisplayName;
   }
}





Coursera - Hundreds of Specializations and courses in business, computer science, data science, and more

2 comments

Write comments
September 28, 2015 at 3:02 AM delete

In ASP.NET MVC 5.1 it's fairly simple, you only need to write just a single line of code.
MVC 5.1 provides new HTML helper for Enum support as drop-down i.e. EnumDropDownListFor helper method. Use this as following

@Html.EnumDropDownListFor(model=>model.EnumtypeProperty)
Below article provide in detail implementation for same

http://modernpathshala.com/Article/1030/enum-support-in-mvc5-1

Reply
avatar
Ehsan Sajjad
AUTHOR
November 8, 2015 at 2:07 PM delete

yes before asp.net mvc 5 we have to write our custom html helper.

Reply
avatar