37 asp.net-mvc model-binding viewmodel asp.net-mvc-3
我有一个视图,列出要添加到平面图的表.从表中获得TableInputModel
允许RectangleTableInputModel
,CircleTableInputModel
等
ViewModel有一个列表,TableInputModel
其中包含所有派生类型.
我对每个派生类型都有局部视图,并且给定了一个List
混合派生类型,框架知道如何渲染它们.
但是,在提交表单时,类型信息会丢失.我尝试使用自定义模型绑定器,但因为类型信息在提交时丢失了,所以它不会工作...
有人曾尝试过这个吗?
Dar*_*rov 69
假设您有以下型号:
public abstract class TableInputModel
{
}
public class RectangleTableInputModel : TableInputModel
{
public string Foo { get; set; }
}
public class CircleTableInputModel : TableInputModel
{
public string Bar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
以下控制器:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以写视图了.
主要观点Index.cshtml
:
@model TableInputModel[]
@using (Html.BeginForm())
{
@Html.EditorForModel()
<input type="submit" value="OK" />
}
Run Code Online (Sandbox Code Playgroud)
和相应的编辑器模板.
~/Views/Home/EditorTemplates/RectangleTableInputModel.cshtml
:
@model RectangleTableInputModel
<h3>Rectangle</h3>
@Html.Hidden("ModelType", Model.GetType())
@Html.EditorFor(x => x.Foo)
Run Code Online (Sandbox Code Playgroud)
~/Views/Home/EditorTemplates/CircleTableInputModel.cshtml
:
@model CircleTableInputModel
<h3>Circle</h3>
@Html.Hidden("ModelType", Model.GetType())
@Html.EditorFor(x => x.Bar)
Run Code Online (Sandbox Code Playgroud)
最后遗漏的难题是该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;
}
}
Run Code Online (Sandbox Code Playgroud)
将在以下地址注册Application_Start
:
ModelBinders.Binders.Add(typeof(TableInputModel), new TableInputModelBinder());
Run Code Online (Sandbox Code Playgroud)
这就是全部.现在,在Index Post操作中,模型数组将使用正确的类型正确初始化.
归档时间: |
|
查看次数: |
12505 次 |
最近记录: |