This one took me a few hours to figure out. I could see that the seeds necessary to pull off what I wanted to accomplish were “planted” the new MVC 2.0, but documentation at this point is just a bit on the light side for some of the new features.
So here is the skinny; Imagine you have a Car Object that has four properties that are fixed, meaning they are perfect candidates for enumerations.

So you create four types for the Car Object
public class Enums
{
public enum Color
{
None=0,
Black,
Red,
NeonOrange
}
public enum DoorCount
{
None=0,
Two,
Four,
Five
}
public enum CarModel
{
None=0,
Family,
BoyRacer,
Bachelor,
Retired
}
public enum VehicleType
{
None=0,
Ute,
Sedan,
Coup,
Van,
SUV
}
}
Great, now you want to make a screen where the person can create a new car. Pretty straight forward in MVC… but I have four properties that are all basically enumerations, unfortunately the are all different lists. I could code up four drop downs, but that’s a lot of typing for the same thing over and over. What would be really cool is if I could somehow use the EditorFor (which uses the Data driven EditorTemplates framework) function where I could pass the field to be edited and the select list to use, and the control would do the rest for me. Good news is I can, not so good news, figuring out how.
Let’s start by doing some data annotations on the model for the car as per His Gu’ness’s instructions.
namespace BloggingMVCSkeleton.Models
{
[MetadataType( typeof( Car_Metadata ) )]
public partial class Car
{
}
internal class Car_Metadata
{
[HiddenInput]
public Guid Uid { get; set; }
[DisplayName( "Choose Car Color" )]
[Required( ErrorMessage = "Color must be selected" )]
public Enums.Color Color { get; set; }
[DisplayName( "Choose Number of Doors (odd # denotes Hatchback)" )]
[Required( ErrorMessage = "Number of doors must be selected" )]
public Enums.DoorCount DoorCount { get; set; }
[DisplayName( "Choose Model" )]
[Required( ErrorMessage = "Model type required" )]
public Enums.CarModel CarModel { get; set; }
[DisplayName( "Vehicle Type" )]
public Enums.VehicleType VehicleType { get; set; }
}
}
Now we need some select lists for those enums, so Let’s add a static method to the Enums class that returns select list items (and uses a NEW enumeration of our enumeration types).
public enum SelectListItemType
{
None = 0 ,
Color ,
DoorCount ,
CarModel ,
VehicleType
}
public static IEnumerable<SelectListItem> SelectListFor (
SelectListItemType selectListItemType ,
int selectedItem = -1 ,
string firstItemPromptText = "" ,
bool includeEmptyFirstItem = false )
{
var selectList = new List<SelectListItem>( );
if ( includeEmptyFirstItem )
{
selectList.Add( new SelectListItem( ) { Text = "" , Value = "" } );
}
else if ( !string.IsNullOrWhiteSpace( firstItemPromptText ) )
{
selectList.Add( new SelectListItem( ) { Text = firstItemPromptText , Value = "" } );
}
switch ( selectListItemType )
{
case SelectListItemType.Color:
selectList.Add( new SelectListItem( )
{
Text = "Black" ,
Value = Color.Black.ToString( ) ,
Selected = ( ( ( int )Color.Black ) == selectedItem )
} );
selectList.Add( new SelectListItem( )
{
Text = "Red" ,
Value = Color.Red.ToString( ) ,
Selected = ( ( ( int )Color.Red ) == selectedItem )
} );
selectList.Add( new SelectListItem( )
{
Text = "NeonOrange" ,
Value = Color.NeonOrange.ToString( ) ,
Selected = ( ( ( int )Color.NeonOrange ) == selectedItem )
} );
break;
case SelectListItemType.DoorCount:
selectList.Add( new SelectListItem( )
{
Text = "2" ,
Value = DoorCount.Two.ToString( ) ,
Selected = ( ( ( int )DoorCount.Two ) == selectedItem )
} );
selectList.Add( new SelectListItem( )
{
Text = "4" ,
Value = DoorCount.Four.ToString( ) ,
Selected = ( ( ( int )DoorCount.Four ) == selectedItem )
} );
... [SNIP] ...
case SelectListItemType.None:
default:
break;
}
return selectList;
}
I admit that last part looks a little ugly, and I can see some seeds that should assist in building up those select list items, but I didn’t want to hold back this entry while I figure that out, I’ll just amend this entry (probably put in a new entry) when I figure it out.
Pressing on for now, and accepting that the last bit didn’t look very elegant, but the pay off is worth it!
So first let’s create the car controller and put in the Index and the Create functionality
public class CarController : Controller
{
//
// GET: /Car/
public ActionResult Index ( )
{
using ( var dc = new Models.CarDataContext( ) )
{
var cars = dc.Cars.ToList( );
return View( cars );
}
}
//
// GET: /Car/Create
public ActionResult Create ( )
{
var car = new Car( );
return View( car );
}
}
Create our views by right mouse clicking, and making them a strongly typed view

Here is what we get…
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor( model => model.Color )%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor( model => model.Color )%>
<%: Html.ValidationMessageFor( model => model.Color )%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.DoorCount) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DoorCount) %>
<%: Html.ValidationMessageFor(model => model.DoorCount) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.CarModel) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.CarModel) %>
<%: Html.ValidationMessageFor(model => model.CarModel) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.VehicleType) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.VehicleType) %>
<%: Html.ValidationMessageFor(model => model.VehicleType) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
Good enough… but is it? couple of things come up, first up, this is for create, now when I want to do the edit page, I’m going to end up with a duplicate of all of this, that means any changes to the model means I have to make changes in two places. That is NOT acceptable! My mantra (that I have really come to fully embrace only in the last two years) is
“… if you have the same thing happening in two places, then Refactor into one place and have two pointers”
Before we go any further let’s run the app and get to the create page to see what we got.

So let’s use the new EditorFor template capabilities as described on MSDN: Walkthrough: Using Templated Helpers to Display Data.
In the View | Car folder let’s create the EditorTemplates folder

Now let’s create a partial view in that folder set up for the Car.

To start with it looks almost identical to the Create page,

But we edit it a bit and we end up with this.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BloggingMVCSkeleton.Models.Car>" %>
<div class="editor-label">
<%: Html.LabelFor( model => model.Color )%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor( model => model.Color )%>
<%: Html.ValidationMessageFor( model => model.Color )%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.DoorCount) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DoorCount) %>
<%: Html.ValidationMessageFor(model => model.DoorCount) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.CarModel) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.CarModel) %>
<%: Html.ValidationMessageFor(model => model.CarModel) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.VehicleType) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.VehicleType) %>
<%: Html.ValidationMessageFor(model => model.VehicleType) %>
</div>
Now back on the Create Page we can modify it to read a-lot more simply, Pay attention to Line 15 below.
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<BloggingMVCSkeleton.Models.Car>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%:Html.EditorFor(model => model) %>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
The real advantage will come with the Edit Page, let’s do that real quickly so you can see why this is worth while right from the start. We modify the controller’s edit to be
public ActionResult Edit ( Guid uid )
{
using ( var dc = new Models.CarDataContext( ) )
{
var car = dc.Cars.FirstOrDefault( c => c.Uid == uid );
return View( car );
}
}
And generate our Edit view, and after a little clean up we get (looking again at line 17):
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<BloggingMVCSkeleton.Models.Car>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit</h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%:Html.EditorFor(model => model) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
So now if I need to modify the car, all I have to do is go edit the Car.ascx in the EditorTemplates folder, and Viola both Edit and Create are automatically updated. So far nothing really spectacular and I still haven’t justified the mess I made inside the Enums class with that static SelectListItem function. So let’s go on to the Enumeration Selects, the interesting take away so far however is I only need to implement the update in the Cars.ascx and both create and edit will get it.
Let’s start with Color:
Being good little MVC programming Children, we DON’T EVER do any code processing in the View, that must all take place in the Controller, so obviously in the Create function we need to get the select list for colors and pass it into the View.
public ActionResult Create ( )
{
var car = new Car( );
var colors = Enums.SelectListFor( Enums.SelectListItemType.Color , firstItemPromptText: " [ Select Color ] " );
ViewData["Colors"] = colors;
return View( car );
}
We don’t need to make any changes to the View, all we need to do is make a quick modification to the Cars.ascx in the EditorTemplates folder
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BloggingMVCSkeleton.Models.Car>" %>
<div class="editor-label">
<%: Html.LabelFor( model => model.Color )%>
</div>
<div class="editor-field">
<%
var selectList= this.ViewData["ColorsSelectList"] as IEnumerable<SelectListItem>;
%>
<%: Html.DropDownListFor( model => model.Color , selectList )%>
<%: Html.ValidationMessageFor( model => model.Color )%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.DoorCount) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DoorCount) %>
<%: Html.ValidationMessageFor(model => model.DoorCount) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.CarModel) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.CarModel) %>
<%: Html.ValidationMessageFor(model => model.CarModel) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.VehicleType) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.VehicleType) %>
<%: Html.ValidationMessageFor(model => model.VehicleType) %>
</div>
Run it and here is what we get

So yes I could do the other four properties exactly the same, but… that would mean that with the exception of which select list I get, I would be repeating almost identical boiler plate and we all know the Manta…
“… if you have the same thing happening in two places, then Refactor into one place and have two pointers”
This is where things begin to get a little tricky. Just as we can make an editor for a whole object we can make an editor for just an particular field on an object. So that just like we have <%: Html.DropDownListFor( model => model.Color , selectList )%> we should also be able to have a <%: Html.EditorFor( model => model.Color , selectList )%> and so we can. And thinking of Inheritance and other object oriented ideas, all of the properties are of some type of Enumeration, so let’s see if we can refactor out a single partial view that can handle any of our enumerations.
Let’s start by creating a partial view in the EditorTemplates folder and set up to be strongly typed for Enum (note: you have to Manually type in “Enum”, it isn’t in the drop down). Let’s give this partial view the logical Name of “EnumeratedType”.

For now, inside of the partial view let’s just copy in what we had for the dropdown for Color

As you can see we have some read squigglies, the error for all three of these is:
‘System.Enum' does not contain a definition for 'Color' and no extension method 'Color' accepting a first argument of type 'System.Enum' could be found
At this point the control is expecting you to just pass in a single value of type Enum, in short the “model” referenced in the code at this point should be paired down to just the single property being handled. So let’s delete the “.Color” for all the lines.
Now we have
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %>
<div class="editor-label">
<%: Html.LabelFor( model => model )%>
</div>
<div class="editor-field">
<%
var selectList= this.ViewData["ColorsSelectList"] as IEnumerable<SelectListItem>;
%>
<%: Html.DropDownListFor( model => model , selectList )%>
<%: Html.ValidationMessageFor( model => model )%>
</div>
Now that we have done that, we can go off to the original Cars.ascx partial view and modify it to call this editor.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BloggingMVCSkeleton.Models.Car>" %>
<%: Html.EditorFor( model => model.Color )%>
<div class="editor-label">
<%: Html.LabelFor(model => model.DoorCount) %>
</div>
... [ SNIP ] ...
and when we run it we now get …

No change, so far so good. Now it’s Refactor payoff time (finally)!
Now I need to modify the EnumeratedTypes.ascx partial view so it will accept all of the enumerated properties for the car. We want the Cars.ascx to look like this:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BloggingMVCSkeleton.Models.Car>" %>
<%: Html.EditorFor( model => model.Color )%>
<%: Html.EditorFor( model => model.DoorCount )%>
<%: Html.EditorFor( model => model.CarModel )%>
<%: Html.EditorFor( model => model.VehicleType )%>
First things first, we need to add the select lists to the view data, so back to the controller. Before I show you the changes I made, I would like you to Note that I VERY carefully named the Enumerations to be the same as the property name of the value on the Car.
public ActionResult Create ( )
{
var car = new Car( );
ViewData["Color"] = Enums.SelectListFor( Enums.SelectListItemType.Color , firstItemPromptText: " [ Select Color ] " );
ViewData["DoorCount"] = Enums.SelectListFor( Enums.SelectListItemType.DoorCount , firstItemPromptText: " [ Select # Doors ] " );
ViewData["CarModel"] = Enums.SelectListFor( Enums.SelectListItemType.CarModel , firstItemPromptText: " [ Select Model ] " );
ViewData["VehicleType"] = Enums.SelectListFor( Enums.SelectListItemType.VehicleType , firstItemPromptText: " [ Select Vehicle Type ] " );
return View( car );
}
Please also note that I modified ViewData[“ColorSelectList”] to be ViewData[“Color”]. This will allow me to look up the select list to use with the property in the EnumeratedTypes.ascx partial view by looking at the name of the property passed in. I could have left “SelectList” in the key, but then I would have to stay with that pattern for the other items. Anyways, here is the new code in the EnumeratedTypes Partial View.
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %>
<div class="editor-label">
<%: Html.LabelFor( model => model )%>
</div>
<div class="editor-field">
<%
//var selectList= this.ViewData["ColorsSelectList"] as IEnumerable<SelectListItem>;
var propName = this.ViewData.ModelMetadata.PropertyName;
var selectList= this.ViewData.FirstOrDefault( i => i.Key == propName ).Value as IEnumerable<SelectListItem>;
%>
<%: Html.DropDownListFor( model => model , selectList )%>
<%: Html.ValidationMessageFor( model => model )%>
</div>
You’ll notice that now I look up the prop name passed into the partial view from the model metadata, then I use that to look up the select list in the view data. If I had wanted to leave the select lists with “SelectList” tacked onto the end then I would have had to do the same for the other selectlists passed into the view data and I would have to modify the linq look up to be
var selectList= this.ViewData.FirstOrDefault( i => i.Key == propName + "SelectList" ).Value as IEnumerable<SelectListItem>;
Ok so that’s the magic, what do we have now on our Create (and Edit page as well)?

So to Recap
Create Code Tree
Code from Controller
public ActionResult Create ( )
{
var car = new Car( );
ViewData["Color"] = Enums.SelectListFor( Enums.SelectListItemType.Color , firstItemPromptText: " [ Select Color ] " );
ViewData["DoorCount"] = Enums.SelectListFor( Enums.SelectListItemType.DoorCount , firstItemPromptText: " [ Select # Doors ] " );
ViewData["CarModel"] = Enums.SelectListFor( Enums.SelectListItemType.CarModel , firstItemPromptText: " [ Select Model ] " );
ViewData["VehicleType"] = Enums.SelectListFor( Enums.SelectListItemType.VehicleType , firstItemPromptText: " [ Select Vehicle Type ] " );
return View( car );
}
Code From Create View
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<BloggingMVCSkeleton.Models.Car>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%:Html.EditorFor(model => model) %>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
Code From Car.ascx (the EditorFor template for car)
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BloggingMVCSkeleton.Models.Car>" %>
<h2>Specify your new Car Properties</h2>
<%: Html.EditorFor( model => model.Color )%>
<%: Html.EditorFor( model => model.DoorCount )%>
<%: Html.EditorFor( model => model.CarModel )%>
<%: Html.EditorFor( model => model.VehicleType )%>
Code from EnumeratedType.ascx (the EditorFor template for enumeration values)
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Enum>" %>
<div class="editor-label">
<%: Html.LabelFor( model => model )%>
</div>
<div class="editor-field">
<%
//var selectList= this.ViewData["ColorsSelectList"] as IEnumerable<SelectListItem>;
var propName = this.ViewData.ModelMetadata.PropertyName;
var selectList= this.ViewData.FirstOrDefault( i => i.Key == propName ).Value as IEnumerable<SelectListItem>;
%>
<%: Html.DropDownListFor( model => model , selectList )%>
<%: Html.ValidationMessageFor( model => model )%>
</div>
All the hard work is done for me in the datatyping. I’m loving this new MVC 2.0!!!