MVC 3使用ModelBinderAttribute将ModelBinding绑定到集合

时间:2013-02-13 12:02:59

标签: asp.net-mvc-3 model-binding

是否可以使用ModelBinderAttribute绑定到集合?

这是我的动作方法参数:

[ModelBinder(typeof(SelectableLookupAllSelectedModelBinder))] List<SelectableLookup> classificationItems

这是我的自定义模型绑定器:

public class SelectableLookupAllSelectedModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var model = bindingContext.Model as SelectableLookup ??
                             (SelectableLookup)DependencyResolver.Current.GetService(typeof(SelectableLookup));

        model.UId = int.Parse(bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue);
        model.InitialState = true;
        model.SelectedState = true;

        return model;
    }
}

以下是此参数的已发布JSON数据:

"classificationItems":["19","20","21","22"]}

以下是ValueProvider的看法:

viewModel.classificationItems[0] AttemptedValue =“19” viewModel.classificationItems[1] AttemptedValue =“20” viewModel.classificationItems[2] AttemptedValue =“21” viewModel.classificationItems[3] AttemptedValue =“22”

这当前没有用,因为首先有一个前缀(“viewModel”)我可以整理,但其次bindingContext.ModelName是“classificationItems”,它是被绑定的参数的名称而不是索引的列表中的项目,即“classificationItems [0]”

我应该补充一点,当我在global.asax中将此绑定器声明为全局ModelBinder时,它可以正常工作......

1 个答案:

答案 0 :(得分:2)

您的自定义模型活页夹用于整个列表,而不仅仅用于每个特定项目。当您通过实现IModelBinder从头开始编写新的绑定器时,您需要处理将所有项添加到List和列表优先级等。这不是简单的代码,请检查DefaultModelBinder here

相反,您可以扩展DefaultModelBinder类,让它像往常一样工作,然后将这两个属性设置为true:

public class SelectableLookupAllSelectedModelBinder: DefaultModelBinder
{

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        //Let the default model binder do its work so the List<SelectableLookup> is recreated
        object model = base.BindModel(controllerContext, bindingContext);

        if (model == null)
            return null; 

        List<SelectableLookup> lookupModel = model as List<SelectableLookup>;
        if(lookupModel == null)
            return model;

        //The DefaultModelBinder has already done its job and model is of type List<SelectableLookup>
        //Set both InitialState and SelectedState as true
        foreach(var lookup in lookupModel)
        {
            lookup.InitialState = true;
            lookup.SelectedState = true;
        }

        return model;          
    }

可以通过向action参数添加bind属性来处理前缀,例如[Bind(Prefix="viewModel")]

所以最后你的action方法参数如下:

[Bind(Prefix="viewModel")]
[ModelBinder(typeof(SelectableLookupAllSelectedModelBinder))] 
List<SelectableLookup> classificationItems