MVC直接在单个对象上调用模型绑定器

时间:2011-09-29 15:09:07

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

有没有办法可以为单个对象调用模型绑定器?

我不想/需要自定义模型绑定器 - 我只想做这样的事情:

MyViewModel1 vModel1 = new MyViewModel1();
InvokeModelBinder(vModel1);

MyViewModel2 vModel2= new MyViewModel2();
InvokeModelBinder(vModel2);

当我完成后,vModel1和vModel2的属性都已绑定到传入请求中的内容。由于我们的控制器/操作的编写方式,我不一定要在操作方法的输入列表中列出vModel1和vModel2(因为最终会有一个可能很长的视图模型列表,可以选择绑定)。

2 个答案:

答案 0 :(得分:8)

使用Controller.UpdateModel

MyViewModel1 vModel1 = new MyViewModel1();
UpdateModel(vModel1);

<强>更新

注意,如果控制器中的ModelState具有验证错误(与传递的模型相关),则UpdateModel(使用任何模型)会抛出异常,尽管UpdateModel成功并且vModel1已更新。因此,应该删除ModelState中的错误,或者将UpdateModel放在try / catch中,然后忽略例外

答案 1 :(得分:2)

这在许多层面都是错误的恕我直言:

  1. 这不是ASP.NET MVC的工作方式。
  2. 您的行为没有明确规定他们期望的数据。
  3. 你从中获得了什么?闻起来很糟糕。
  4. 模型绑定由反射驱动。在调用操作之前,它将反映方法参数列表,并且对于每个对象及其属性,它将调用模型绑定器以从各种值提供程序(形成POST值提供程序,url参数等)查找每个属性的值。在模型绑定期间,还完成了ModelState验证。

    因此,如果不使用默认的ASP.NET MVC来执行此操作,那么您将失去所有这些。

    即使您手动获取类似的模型装订器:

    IModelBinder modelBinder = ModelBinders.Binders.GetBinder(typeof(MyObject));
    MyObject myObject = (MyObject ) modelBinder.BindModel(this.ControllerContext, ** ModelBindingContext HERE**);
    

    你可以看到你需要初始化一个ModelBindingContext,这是ASP.NET MVC将根据它反映的当前属性在内部做的事情。这是从ASP.NET MVC源代码中剪切的:

    protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) {
    // collect all of the necessary binding properties
    Type parameterType = parameterDescriptor.ParameterType;
    IModelBinder binder = GetModelBinder(parameterDescriptor);
    IDictionary<string, ValueProviderResult> valueProvider = controllerContext.Controller.ValueProvider;
    string parameterName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
    Predicate<string> propertyFilter = GetPropertyFilter(parameterDescriptor);
    
    // finally, call into the binder
    ModelBindingContext bindingContext = new ModelBindingContext() {
        FallbackToEmptyPrefix = (parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefix not specified
        ModelName = parameterName,
        ModelState = controllerContext.Controller.ViewData.ModelState,
        ModelType = parameterType,
        PropertyFilter = propertyFilter,
        ValueProvider = valueProvider
    };
    object result = binder.BindModel(controllerContext, bindingContext);
    return result;
    

    }