Saturday, June 1, 2013

MVC 4 and Extension method : How to bind an Enum to a DropDownList


ASP.NET MVC 3 is delivered with a lot of « Helpers ». These methods help the developer to improve his productivity and the quality of his Html code. If you don’t know yet the MVC Html Helper, you can read the MSDN page about HtmlHelper or read this article with plenty of examples.
Before reading this post and if you don’t know extension methods in .NET, you can read (again!) this article.
Okay, now you’ve learned a lot about Html Helper and methods extension, we can start!
I’m currently on an ASP.NET MVC 3 project and developers need to produce quick and clean HTML forms. MVC Helper has a clean and useful method to bind a collection in a DropDownList and that works perfectly for Enums.
Imagine we have two Enums :
1
2
3
4
5
6
7
8
public enum Vertebrate
{
    Fish,
    Mammals,
    Reptile,
    Amphibians,
    Birds
}
1
2
3
4
5
6
7
8
9
public enum Invertebrate
{
    Arachnids,
    Insects,
    Mollusks,
    Crustacean,
    Echinoderms,
    Protozoa
}
We want to write the less code possible to bind this enum in a dropdownlist and bind the list with our model. With MVC Helper we could write something like that :
1
@Html.DropDownListFor(model => model.Vertebrate, new SelectList(Enum.GetValues(typeof(EnumHtmlHelper.Models.Invertebrate))), "Please select a vertebrate")
That is pretty simple isn’t it? But what I don’t like in this code is the “Technical” part. We need to instantiate the “SelectList” and get all the values of the enum with “Enum.GetValue” and finally we need to specify the “type of” the enum. Boring isn’t it?
And when you have big and complex forms in you view, it’s a good practice to simplify code like that. So, what’s the simplest call we could make in our view? Perhaps something like that :
1
@Html.EnumDropDownListFor(model => model.Vertebrate, "Please select a vertebrate")
Here, we don’t have complex thing just the binding between the DropDownList with the lamda Expression and, this is optional, the first line of our dropdownlist.
Okay, let’s take a lot deeply in the code to understand how do we build the extension method.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace EnumHtmlHelper.Helper
{
    public static class EnumDropDownList
    {
        public static HtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression, string firstElement)
        {
            var typeOfProperty = modelExpression.ReturnType;
            if(!typeOfProperty.IsEnum)
                throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));
 
            var enumValues = new SelectList(Enum.GetValues(typeOfProperty));
            return htmlHelper.DropDownListFor(modelExpression, enumValues, firstElement);
        }
    }
}
First, we need to place our extension class in a namespace with a simple and meaning name. Don’t forget that your extension method will be visible only when the extension namespace is present in the using statement of your view.
Our method has three parameters.
  • The first parameter is the object on which we want to add an extension.
  • The second parameter is the lambda expression.
  • The third parameter is the first element of our dropdownlist.
The expression “modelExpression” is targeting a model property. Therefore we know the return type of this element. So we are able to get all the values of the Enum type. Finaly, we just have to create the SelectList and call the “real” DropDownListFor method.
If we take a look at our view, we just need to add the namespace where the extension is and call the EnumDropDownList method on the @Html object.
1
2
3
4
5
6
7
8
9
@using EnumHtmlHelper.Helper
 
@model EnumHtmlHelper.Models.IndexModel
 
<h2>Animals</h2>
<p>@Html.LabelFor(model => model.Vertebrate)</p>
@Html.EnumDropDownListFor(model => model.Vertebrate, "Please select a vertebrate")
<p>@Html.LabelFor(model => model.Invertebrate)</p>
@Html.EnumDropDownListFor(model => model.Invertebrate, "Please select an invertebrate")



No comments:

Find a cool free stuff everyday

Giveaway of the Day

Hiren Bharadwa's Posts

DotNetJalps