2010-02-25 7 views
3

J'ai un scénario dans lequel j'aimerais modifier le comportement de DefaultModelBinder dans la façon dont il se lie à une liste d'énumérations.Existe-t-il un moyen pour que DefaultModelBinder ignore les éléments vides lors de la liaison à une liste? <Enum>

J'ai un ENUM ...

public enum MyEnum { FirstVal, SecondVal, ThirdVal } 

et une classe pour un modèle ...

public class MyModel 
{ 
    public List<MyEnum> MyEnums { get; set; } 
} 

et le corps POST est ...

MyEnums=&MyEnums=ThirdVal 

Actuellement , après la liaison du modèle, la propriété MyEnums contiendra ...

[0] = FirstVal 
[1] = ThirdVal 

Est-il possible de dire au classeur modèle d'ignorer la valeur vide dans les données publiées afin que la propriété MyEnums puisse ressembler à ceci?

[0] = ThirdVal 

Répondre

6

Vous pouvez écrire un classeur modèle personnalisé pour 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); 
    } 
} 

qui est enregistré dans Application_Start:

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    RegisterRoutes(RouteTable.Routes); 
    ModelBinders.Binders.Add(typeof(MyModel), new MyModelModelBinder()); 
} 

MISE À JOUR:

Comme demandé dans le commentaires se ction voici comment rendre le classeur précédent plus générique:

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); 
} 
+0

J'aime ça, merci. Savez-vous comment cela pourrait fonctionner pour n'importe quel type Enum? – JeremyWeir

+0

Oui, voir ma mise à jour. –

+0

Wow, a bien fonctionné, merci. – JeremyWeir