我有一个视图,列出要添加到平面图的表格。表格来自TableInputModel
,以允许RectangleTableInputModel
,CircleTableInputModel
等
ViewModel有一个TableInputModel
列表,它们都是派生类型之一。
我对每个派生类型都有部分视图,并且给定了List
混合派生类型,框架知道如何呈现它们。
但是,在提交表单时,类型信息会丢失。我尝试使用自定义模型绑定器,但因为类型信息在提交时丢失了,所以它不会工作......
以前有人试过吗?
答案 0 :(得分:68)
假设您有以下型号:
public abstract class TableInputModel
{
}
public class RectangleTableInputModel : TableInputModel
{
public string Foo { get; set; }
}
public class CircleTableInputModel : TableInputModel
{
public string Bar { get; set; }
}
以下控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new TableInputModel[]
{
new RectangleTableInputModel(),
new CircleTableInputModel()
};
return View(model);
}
[HttpPost]
public ActionResult Index(TableInputModel[] model)
{
return View(model);
}
}
现在你可以写视图了。
主视图Index.cshtml
:
@model TableInputModel[]
@using (Html.BeginForm())
{
@Html.EditorForModel()
<input type="submit" value="OK" />
}
和相应的编辑器模板。
~/Views/Home/EditorTemplates/RectangleTableInputModel.cshtml
:
@model RectangleTableInputModel
<h3>Rectangle</h3>
@Html.Hidden("ModelType", Model.GetType())
@Html.EditorFor(x => x.Foo)
~/Views/Home/EditorTemplates/CircleTableInputModel.cshtml
:
@model CircleTableInputModel
<h3>Circle</h3>
@Html.Hidden("ModelType", Model.GetType())
@Html.EditorFor(x => x.Bar)
并且最终遗失的难题是TableInputModel
类型的自定义模型绑定器,它将使用已发布的隐藏字段值来获取类型并实例化正确的实现:
public class TableInputModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ModelType");
var type = Type.GetType(
(string)typeValue.ConvertTo(typeof(string)),
true
);
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
}
}
将在Application_Start
注册:
ModelBinders.Binders.Add(typeof(TableInputModel), new TableInputModelBinder());
这就是全部。现在,在Index Post操作中,模型数组将使用正确的类型正确初始化。
答案 1 :(得分:2)
mvccontrib中有"Derived Type Model Binder"。但是,遗憾的是,mvccontrib版本3中没有这样的绑定器