2

当请求包含表单变量的平面集合时,我很难让自定义模型绑定器工作。

我有一个包含嵌套 ViewModel 的 ViewModel 类,例如

public class ViewModel1
{
    public long Id { get; set; }
    public ViewModel2 NestedType { get; set; }
}

public class ViewModel2
{
    public string Name { get; set; }
    public string Surname { get; set; }
}

我的问题是,如果我使用 Fiddler 提交带有 NestedType.Name 表单变量的请求,那么我的自定义模型绑定器执行得很好,但是,我必须处理的请求是我无法控制的,在这种情况下,它是通过来自 JQGrid 实例的 ajax 请求发布的,并且是“扁平的”,即

Id=5
Name=firstname
Surname=surname

不是

Id=5
NestedType.Name=firstname
NestedType.Surname=surname

有什么办法可以让它工作吗?

提前致谢。

编辑:

为了澄清一点,我的控制器操作如下所示:

public ActionResult GridEditRow(ViewModel1 viewModel)

如下所述,我宁愿在执行控制器代码之前触发自定义绑定器,而不是调用 TryUpdateModel()。

4

4 回答 4

1

不是最好的解决方案,但您可以为该类型添加另一个参数:

public ActionResult GridEditRow(ViewModel1 viewModel, ViewModel2 viewModel2)

这应该绑定 Name 属性,即使它没有正确的前缀。

于 2013-08-12T14:16:14.550 回答
1

尝试这个:

var viewModel = new ViewModel1();
UpdateModel(viewModel.NestedType);
于 2013-08-12T13:40:07.140 回答
0

可能您可以通过以下方式更改 ActionResult:

public ActionResult GridEditRow(int id, string firstname, string surname)
{
  VewModel2 model2 = new VewModel2
{
Name  = firstname,
Surname = surname
}

  VewModel1 model1 = new VewModel1
{
Id = id,
NestedType  = model2 
}

return View(model1 )  

}
于 2013-08-12T16:15:16.090 回答
0

我遇到了类似的问题。正如您所假设的那样,可能的决定之一是自定义模型绑定器。虽然这个问题很老,但我会把我的答案放在这里(因为为什么不呢?)。所以自定义模型绑定器的代码如下。

public class CustomModelBinder : DefaultModelBinder {
        protected override void BindProperty(
            ControllerContext controllerContext, 
            ModelBindingContext bindingContext, 
            System.ComponentModel.PropertyDescriptor propertyDescriptor) {
                if (bindingContext.ModelType == typeof(ViewModel1)) {
                    var name = propertyDescriptor.Name;

                    // Try to implement default binding.
                    // Also one could try base.BindProperty(...).
                    var value = bindingContext.ValueProvider.GetValue(name);
                    if (value != null)
                        propertyDescriptor.SetValue(bindingContext.Model, value.ConvertTo(propertyDescriptor.PropertyType));

                    // If the default binding is not working then search for nested values.
                    else {
                        value = bindingContext.ValueProvider.GetValue("NestedType." + name);
                        if(value != null)
                            propertyDescriptor.SetValue(bindingContext.Model, value.ConvertTo(propertyDescriptor.PropertyType));
                    }
                } else
                    base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }
    }

在 Global.asax 中注册活页夹:

ModelBinders.Binders.Add(typeof(ViewModel1), new CustomModelBinder());

注册的另一种可能性是在控制器的操作中使用属性。

我想这个决定比其他决定更普遍,但也更慢(因为反射)。

对我有帮助的参考资料:http: //dotnetslackers.com/articles/aspnet/Understanding-ASP-NET-MVC-Model-Binding.aspx

于 2014-12-22T10:28:44.203 回答