Asp.net mvc 3 MVC 3自定义模型绑定到平面形式变量结构

Asp.net mvc 3 MVC 3自定义模型绑定到平面形式变量结构,asp.net-mvc-3,custom-model-binder,Asp.net Mvc 3,Custom Model Binder,当请求包含表单变量的平面集合时,我很难让自定义模型绑定器工作 我有一个ViewModel类,它包含一个嵌套的ViewModel,例如 public class ViewModel1 { public long Id { get; set; } public ViewModel2 NestedType { get; set; } } public class ViewModel2 { public string Name { get; set; } public

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

我有一个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
不是

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

提前谢谢

编辑:

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

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());
注册的另一种可能性是在控制器的操作中使用属性

我认为这个决定比其他决定更具普遍性,但也较慢(因为反射)


帮助我的ref:.

你的意思是,通过JQuery Ajax表单提交,在Post Action方法中,你试图通过表单集合获取Nested2.Name?简而言之,是的,这是正确的,谢谢你,但我希望在我的控制器操作代码之前,我可以在模型绑定期间使它工作。我对我的问题做了一些修改,最后还是用了这个问题,虽然不完美,但却是我能找到的最干净的解决方案。干杯。是的,我可以这么做,问题是那些视图模型只是示例,真实的模型有很多属性,所以方法签名会有点笨拙。另外,嵌套类型嵌套在应用程序其他位置的其他viewmodel类型中。谢谢你的回复,谢谢你的建议。我可以这样做,但随后必须在操作中指定viewmodel.NestedType=viewModel2,这有点笨拙。我希望自定义模型绑定器可以将功能包装在一个位置,因为这不是应用程序中出现嵌套viewmodel的唯一位置。不过谢谢你的帮助:)
ModelBinders.Binders.Add(typeof(ViewModel1), new CustomModelBinder());