当请求包含表单变量的平面集合时,我很难让自定义模型绑定器工作。
我有一个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()。
试试这个:
var viewModel = new ViewModel1();
UpdateModel(viewModel.NestedType);
不是最好的解决方案,但您可以为该类型添加另一个参数:
public ActionResult GridEditRow(ViewModel1 viewModel, ViewModel2 viewModel2)
这应该绑定Name属性,即使它没有正确的前缀。
您可以通过以下方式更改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 )
}
我也遇到过类似的问题。正如您所设想的,其中一个可能的决策是自定义模型绑定器。虽然这个问题已经过时了,但我将把我的答案放在这里(因为为什么不呢?)。因此,自定义模型绑定器的代码如下。
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。