You could write a custom model binder for MyModel:
public class MyModelModelBinder : DefaultModelBinder
{
protected override void SetProperty(
ControllerContext controllerContext,
ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor,
object value)
{
if (value is ICollection<MyEnum>)
{
var myEnums = controllerContext.HttpContext.Request[propertyDescriptor.Name];
if (!string.IsNullOrEmpty(myEnums))
{
var tokens = myEnums.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries);
value = tokens.Select(x => (MyEnum)Enum.Parse(typeof(MyEnum), x)).ToList();
}
}
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
}
}
which is registered in Application_Start
:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders.Add(typeof(MyModel), new MyModelModelBinder());
}
UPDATE:
As requested in the comments section here's how to make the previous binder more generic:
protected override void SetProperty(
ControllerContext controllerContext,
ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor,
object value)
{
var collection = value as IList;
if (collection != null && collection.GetType().IsGenericType)
{
var genericArgument = collection
.GetType()
.GetGenericArguments()
.Where(t => t.IsEnum)
.FirstOrDefault();
if (genericArgument != null)
{
collection.Clear();
var enumValues = controllerContext.HttpContext
.Request[propertyDescriptor.Name];
var tokens = enumValues.Split(
new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var token in tokens)
{
collection.Add(Enum.Parse(genericArgument, token));
}
}
}
base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
}