C# 如何在Asp.NETMVC4中绑定多态模型中的复杂属性?
我需要基于派生类型创建一个动态输入表单,但在传递到控制器的POST方法时,无法正确绑定复杂属性。其他属性绑定良好。以下是我所拥有的一个人为的例子: 型号C# 如何在Asp.NETMVC4中绑定多态模型中的复杂属性?,c#,model-view-controller,model-binding,custom-model-binder,C#,Model View Controller,Model Binding,Custom Model Binder,我需要基于派生类型创建一个动态输入表单,但在传递到控制器的POST方法时,无法正确绑定复杂属性。其他属性绑定良好。以下是我所拥有的一个人为的例子: 型号 public abstract class ModelBase {} public class ModelDerivedA : ModelBase { public string SomeProperty { get; set; } public SomeType MySomeType{ get;
public abstract class ModelBase {}
public class ModelDerivedA : ModelBase
{
public string SomeProperty { get; set; }
public SomeType MySomeType{ get; set; }
public ModelDerivedA()
{
MySomeType = new SomeType();
}
}
public class SomeType
{
public string SomeTypeStringA { get; set; }
public string SomeTypeStringB { get; set; }
}
自定义模型活页夹
[HttpPost]
public ActionResult GetDynamicForm([ModelBinder(typeof(BaseViewModelBinder))] ModelBase model)
{
// model HAS values for SomeProperty
// model has NO values for MySomeType
}
活页夹基于以下答案:
控制器
[HttpPost]
public ActionResult GetDynamicForm([ModelBinder(typeof(BaseViewModelBinder))] ModelBase model)
{
// model HAS values for SomeProperty
// model has NO values for MySomeType
}
查看摘录
@Html.Hidden("ModelType", Model.GetType())
@Html.Test(Model);
JavaScript
@Html.Hidden("ModelType", Model.GetType())
@Html.Test(Model);
表单是使用$发布的。ajax
使用数据:$(this).serialize()
,如果我调试,它将显示正确填充的表单数据
所有属性都填充在模型中,不包括SomeType
的属性。我需要做哪些更改才能填充它们
谢谢尝试将默认构造函数添加到您的
ModelDerivedA
以初始化MySomeType
public class ModelDerivedA : ModelBase
{
public ModelDerivedA()
{
MySomeType = new SomeType();
}
}
未填充值,因为您正在创建以下类型的新实例:
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
并返回不正确的相同模型
做下面这样的事情
ValueProviderResult valueResult;
bindingContext.ModelState.SetModelValue("ModelType", valueResult);
return valueResult;
下面是关于modelBinder的非常好的讨论
我通过以下方式解决了眼前的问题:
FormvalueProvider
的实例(以访问已发布的内容)FormValueProvider中的匹配值
private FormValueProvider vp;
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
var type = Type.GetType(
(string)typeValue.ConvertTo(typeof(string)),
true
);
if (!typeof(ModelBase).IsAssignableFrom(type))
{
throw new InvalidOperationException("Bad Type");
}
var model = Activator.CreateInstance(type);
vp = new FormValueProvider(controllerContext);
bindingContext.ValueProvider = vp;
SetModelPropertValues(model);
return model;
}
private void SetModelPropertValues(object obj)
{
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
var elems = propValue as IList;
if (elems != null)
{
foreach (var item in elems)
{
this.SetModelPropertValues(item);
}
}
else
{
if (property.PropertyType.Assembly == objType.Assembly)
{
this.SetModelPropertValues(propValue);
}
else
{
property.SetValue(obj, this.vp.GetValue(property.Name).AttemptedValue, null);
}
}
}
}
任何使用它的人都可能需要使它更加健壮,以满足他们的需求
作为解决这类问题的一般方法,听到这种方法有什么缺点,我会非常感兴趣
然而,我希望这篇文章能在某些情况下有所帮助。你的意思是什么,请解释一下?这个构造函数应该创建一个
SomeType
的实例。但是它会通过填充表单字段来解决问题吗?@Max,谢谢,在我的示例中这是一个问题,修复后它不会修复绑定问题。@davy它不会修复绑定问题。谢谢@Jenish,但是不是所有的属性都是空的吗(不仅仅是复杂的财产)?是的,我不能让它工作,但我今天没有花很多时间在它上。