几天来,我一直在尝试阅读有关此 DefaultModelBinder 的信息,但我仍然很困惑。我正在使用 MVC 4 和 EF 5 TablePerHiarchy 结构。
我的问题是我有一个资源基类:
public class Resource : PocoBaseModel
{
private int _resourceID;
private string _title;
private string _description;
//public accessors
}
有子类(DVD、电子书、书籍等)
public class DVD : Resource
{
private string _actors;
//more fields and public accessors
}
我的控制器代码使用自定义 ModelBinder
[HttpPost]
public ActionResult Create([ModelBinder(typeof(ResourceModelBinder))] Resource resource)
{
//controller code
}
public class ResourceModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
var type = controllerContext.HttpContext.Request.Form["DiscriminatorValue"];
bindingContext.ModelName = type;
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, resourceTypeMap[type]);
return base.BindModel(controllerContext, bindingContext);
}
static Dictionary<string, Type> resourceTypeMap = new Dictionary<string, Type>
{
{"Resource", typeof(Resource)},
{"Book", typeof(Book)},
{"DVD", typeof(DVD)},
{"EBook", typeof(EBook)},
{"Hardware", typeof(Hardware)},
{"Software", typeof(Software)}
};
}
这样我就可以将我的视图传递给资源(作为 DVD、书籍或任何其他类型)
@model Models.Resource
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm("Create", "Admin", null, FormMethod.Post, null))
{
@Html.ValidationSummary(true)
<fieldset>
<legend>Resource</legend>
@Html.HiddenFor(model => model.ResourceID)
@Html.HiddenFor(model => model.ResourceTypeID)
@Html.HiddenFor(model => model.Committed)
@Html.Partial("_CreateOrEdit", Model)
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
并根据其派生属性绑定它,这些属性发生在部分视图内的开关中。
@using Models.ViewModels;
@using Models.ResourceTypes;
@using Helper;
@model Models.Resource
@Html.HiddenFor(model => Model.DiscriminatorValue);
<table cellspacing="2" cellpadding="2" border="0">
@{
string type = Model.DiscriminatorValue;
switch (type)
{
case "Book":
Book book = (Book)Model;
<tr>
<td colspan="2">
<div class="editor-label" style="padding-top: 15px;">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.Title, new { style = "width: 750px; height: 65px;" })
@Html.ValidationMessageFor(model => model.Title)
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => book.Edition)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => book.Edition, new { style = "width: 150px;" })
@Html.ValidationMessageFor(model => book.Edition)
</div>
</td>
<td>
<div class="editor-label">
@Html.LabelFor(model => book.Author)
</div>
<div class="editor-field">
@Html.EditorFor(model => book.Author)
@Html.ValidationMessageFor(model => book.Author)
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => book.Pages)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => book.Pages, new { style = "width: 75px;" })
@Html.ValidationMessageFor(model => book.Pages)
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="editor-label">
@Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.Description, new { style = "width: 750px; height: 105px;" })
@Html.ValidationMessageFor(model => model.Description)
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div class="editor-label">
@Html.LabelFor(model => model.AdminNote)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.AdminNote, new { style = "width: 750px; height: 105px;" })
@Html.ValidationMessageFor(model => model.AdminNote)
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
@{ int copies = Model == null ? 1 : Model.Copies; }
@Html.LabelFor(model => model.Copies)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.Copies, new { style = "width: 75px;", @Value = copies.ToString() })
@Html.ValidationMessageFor(model => model.Copies)
</div>
</td>
</tr>
<tr>
<td>
<div class="editor-label">
@Html.LabelFor(model => book.ISBN10)
</div>
<div class="editor-field">
@Html.EditorFor(model => book.ISBN10)
@Html.ValidationMessageFor(model => book.ISBN10)
</div>
</td>
<td>
<div class="editor-label">
@Html.LabelFor(model => book.ISBN13)
</div>
<div class="editor-field">
@Html.EditorFor(model => book.ISBN13)
@Html.ValidationMessageFor(model => book.ISBN13)
</div>
</td>
</tr>
break;
我的第一个问题是,当我将表单发布回来时,它作为资源而不是作为强制类型返回(所以我丢失了所有派生类型属性),这就是我创建 ResourceModelBinder 的原因。现在它正确地绑定/回发强制转换的类型,但它不绑定资源的基类属性,如 Title、ResourceID、ResourceTypeID..
谁能帮我理解我所缺少的,以便它实际上绑定了基础资源类属性以及派生类型属性。?