我有一个类似下面这样的操作方法。
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Form newForm)
{
...
}我有一个包含以下类的模型,我希望从ajax JSON数据中加载数据。
public class Form
{
public string title { get; set; }
public List<FormElement> Controls { get; set; }
}
public class FormElement
{
public string ControlType { get; set; }
public string FieldSize { get; set; }
}
public class TextBox : FormElement
{
public string DefaultValue { get; set; }
}
public class Combo : FormElement
{
public string SelectedValue { get; set; }
}这是JSON数据。
{ "title": "FORM1",
"Controls":
[
{ "ControlType": "TextBox", "FieldSize": "Small" ,"DefaultValue":"test"},
{ "ControlType": "Combo", "FieldSize": "Large" , "SelectedValue":"Option1" }
]
}
$.ajax({
url: '@Url.Action("Create", "Form")',
type: 'POST',
dataType: 'json',
data: newForm,
contentType: 'application/json; charset=utf-8',
success: function (data) {
var msg = data.Message;
}
});DefaultModelBinder正在处理嵌套的对象结构,但它不能解析不同的子类。
用各自的子类加载列表的最佳方式是什么?
发布于 2012-12-20 17:47:23
我已经研究了mvc DefaultModelBinder实现的代码。在绑定模型DefaultModelBinder时,使用GetModelProperties()查找模型的属性。以下是DefaultModelBinder查找属性的方式:
protected virtual ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) {
return TypeDescriptorHelper.Get(bindingContext.ModelType);
}TypeDescriptorHelper.Get使用的是ModelType类型(在我的例子中是FormElement),因此不会检索子类(TextBox,Combo)的属性。
您可以重写该方法并更改行为以检索特定子类型,如下所示。
protected override System.ComponentModel.PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
Type realType = bindingContext.Model.GetType();
return new AssociatedMetadataTypeTypeDescriptionProvider(realType).GetTypeDescriptor(realType).GetProperties();
}
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
ValueProviderResult result;
result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ControlType");
if (result == null)
return null;
if (result.AttemptedValue.Equals("TextBox"))
return base.CreateModel(controllerContext,
bindingContext,
typeof(TextBox));
else if (result.AttemptedValue.Equals("Combo"))
return base.CreateModel(controllerContext,
bindingContext,
typeof(Combo));
return null;
}https://stackoverflow.com/questions/13960120
复制相似问题