我有一个视图列出被添加到平面图的表。表派生自TableInputModel以允许RectangleTableInputModel,CircleTableInputModel等
viewmodel有一个TableInputModel的列表,它们都是派生类型之一。
我有一个部分视图的每个派生类型,并给出一个混合派生类型的列表框架知道如何渲染它们。
但是,在提交表单时,类型信息丢失。我试过一个自定义模型绑定器,但因为类型信息丢失时,它提交,它不工作…
有没有人试过这个?
解决方法
假设您有以下型号:
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动作中,模型数组将正确地用正确的类型初始化。