I’ve really been enjoying the html helpers baked into the ASP.Net MVC framework. To compliment the SelectList extensions that I use, I often use this extension as well. It displays a drop down of enum values for the specified property. It will attempt to get the name via the DisplayAttribute. If the attribute is not present, then it will just get the name from the enum value.
I created an extension method to get the Name of an enum value (as described above):
private static readonly Dictionary<Enum, string> NameCache = new Dictionary<Enum, string>(); public static string GetName(this Enum type) { if (NameCache.ContainsKey(type)) return NameCache[type]; var enumType = type.GetType(); var info = enumType.GetField(type.ToString()); if (info == null) return string.Empty; var displayAttribute = info.GetCustomAttributes(false).OfType<DisplayAttribute>().FirstOrDefault(); var value = string.Empty; if (displayAttribute != null) value = displayAttribute.GetName() ?? string.Empty; NameCache.Add(type, value); return value; }
I then make use of that extension with the enum dropdown helper:
public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) { return htmlHelper.DropDownListForEnum(expression, null, null); } public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes) { return htmlHelper.DropDownListForEnum(expression, new RouteValueDictionary(htmlAttributes)); } public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes) { return htmlHelper.DropDownListForEnum(expression, null, htmlAttributes); } public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel) { return htmlHelper.DropDownListForEnum(expression, optionLabel, null); } public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel, object htmlAttributes) { return htmlHelper.DropDownListForEnum(expression, optionLabel, null); } public static MvcHtmlString DropDownListForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string optionLabel, IDictionary<string, object> htmlAttributes) { if (expression == null) throw new ArgumentNullException("expression"); var member = expression.Body as MemberExpression; if (member == null) throw new ArgumentNullException("expression"); var selectedValue = string.Empty; var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); if (metadata.Model != null) { selectedValue = metadata.Model.ToString(); } var enumType = Nullable.GetUnderlyingType(member.Type) ?? member.Type; var listItems = new List<SelectListItem>(); foreach (var name in Enum.GetNames(enumType)) { var type = Enum.Parse(enumType, name) as Enum; listItems.Add(new SelectListItem { Text = type.GetName(), Value = name, Selected = name == selectedValue }); } return htmlHelper.DropDownListFor(expression, listItems, optionLabel, htmlAttributes); }
The beauty of this extension method is that it uses the DropDownListFor(…) helper baked into the framework already. So validation, etc is wired up for me. Also worth noting, this extension works with nullable and non-nullable properties. Hope this helps someone save some time…