有没有办法有绑定到一个List&LT当DefaultModelBinder忽略空项目;枚举> [英] Is there a way to have the DefaultModelBinder ignore empty items when binding to a List<Enum>

查看:96
本文介绍了有没有办法有绑定到一个List&LT当DefaultModelBinder忽略空项目;枚举>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一种情况,我想改变它是如何结合枚举的列表DefaultModelBinder的行为。

我有一个枚举...

 公共枚举MyEnum {Firs​​tVal,SecondVal,ThirdVal}

和一个模型类...

 公共类为MyModel
{
    公开名单< MyEnum> MyEnums {搞定;组; }
}

和POST身体...

  MyEnums =安培; MyEnums = ThirdVal

目前,模型绑定之后,MyEnums属性将包含...

  [0] = FirstVal
[1] = ThirdVal

是有办法告诉模型绑定忽略已发布数据的空值,以便MyEnums财产可能看起来像下面的?

  [0] = ThirdVal


解决方案

您可以写为MyModel自定义模型绑定:

 公共类MyModelModelBinder:DefaultModelBinder
{
    保护覆盖无效的SetProperty(
        ControllerContext controllerContext,
        ModelBindingContext BindingContext中,
        的PropertyDescriptor PropertyDescriptor的,
        对象值)
    {
        如果(值的ICollection< MyEnum>)
        {
            VAR myEnums = controllerContext.HttpContext.Request [propertyDescriptor.Name]
            如果(!string.IsNullOrEmpty(myEnums))
            {
                VAR令牌= myEnums.Split(新[] {','},StringSplitOptions.RemoveEmptyEntries);
                值= tokens.Select(X =>(MyEnum)Enum.Parse(typeof运算(MyEnum),X))了ToList();
            }
        }
        base.SetProperty(controllerContext,BindingContext中,PropertyDescriptor的,价值);
    }
}

这是在的Application_Start 注册

 保护无效的Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    的RegisterRoutes(RouteTable.Routes);
    ModelBinders.Binders.Add(typeof运算(为MyModel),新MyModelModelBinder());
}


更新:

由于在评论部分要求这里是如何使previous粘结剂更通用的:

 保护覆盖无效的SetProperty(
    ControllerContext controllerContext,
    ModelBindingContext BindingContext中,
    的PropertyDescriptor PropertyDescriptor的,
    对象值)
{
    VAR收集=值作为IList的;
    如果(集合= NULL&放大器;!&安培; collection.GetType()IsGenericType。)
    {
        VAR genericArgument =集合
            .GetType()
            .GetGenericArguments()
            。凡(T => t.IsEnum)
            .FirstOrDefault();        如果(genericArgument!= NULL)
        {
            collection.Clear();
            VAR enumValues​​ = controllerContext.HttpContext
                .Request [propertyDescriptor.Name]
            VAR令牌= enumValues​​.Split(
                新的[] {','},StringSplitOptions.RemoveEmptyEntries);
            的foreach(在令牌VAR令牌)
            {
                collection.Add(Enum.Parse(genericArgument,令牌));
            }
        }
    }
    base.SetProperty(controllerContext,BindingContext中,PropertyDescriptor的,价值);
}

I have a scenario where I'd like to change the behavior of the DefaultModelBinder in how it binds to a List of enums.

I have an enum...

public enum MyEnum { FirstVal, SecondVal, ThirdVal }

and a class for a model...

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

and the POST body is...

MyEnums=&MyEnums=ThirdVal

Currently, after model binding, the MyEnums property will contain...

[0] = FirstVal
[1] = ThirdVal

Is there was a way to tell the model binder to ignore the empty value in the posted data so that MyEnums property could look like the following?

[0] = ThirdVal

解决方案

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

这篇关于有没有办法有绑定到一个List&LT当DefaultModelBinder忽略空项目;枚举&GT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆