Ok guys. I've looked up a few ways to do this because I was tired of writing stupid work around to get past this deficiency in the .Net framework. Based on a couple of threads, I have composed the following solution.
Disclaimer, this is not a totally automated solution, so it will not work for all. Given my implementation, it works. Maybe my way will help someone else design something that will work for them.
First, I created an enum respository. The enums don't have to reside here, but they would need to be visible from the repository.
In the repository, I created a class and a public static property to expose a list of enum types.
namespace MyApp.Enums
{
public enum ATS_Tabs { TabOne = 0, TabTwo = 1, TabThree = 2, TabFour = 3, TabFive = 4 };
public class ModelEnums
{
public static IEnumerable<Type> Types
{
get
{
List<Type> Types = new List<Type>();
Types.Add(typeof(ATS_Tabs));
return Types;
}
}
}
}
Next, I created a model binder and implemented the IModelBinder interface (ref. kdawg's comment and link).
namespace MyApp.CustomModelBinders
{
public class EnumModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try
{
return Enum.ToObject(Type.GetType(bindingContext.ModelType.AssemblyQualifiedName), Convert.ToInt32(valueResult.AttemptedValue));
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
}
It might help to add some code to ensure the conversion of valueResult.AttemptedValue doesn't fail.
Next, I looped through the list of enum types I created above and added model binders for them (...in Global.asax.cs).
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
foreach (Type type in ModelEnums.Types)
{
ModelBinders.Binders.Add(type, new EnumModelBinder());
}
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
I admit, this it not the most intuitive way, but it works great for me. Feel free to let me know if I can optimize this.