我正在开发一个应用程序,我需要能够在运行时从数据库加载对象属性。客户希望能够向数据库添加属性并将其显示在应用程序中。我通过为我的模型提供包含名称,类型和值的Field对象列表来实现此目的。这适用于显示和编辑项目属性,但我在编辑器视图中遇到验证问题。谢谢你的帮助。
我希望能够在我的编辑操作中执行此操作:
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
普通视图:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(model => model.ID)
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
</fieldset>
}
我需要做什么:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(model => model.ID)
for(i = 1 to n) {
<div class="editor-label">
@Html.LabelFor(model => model.Fields[i].Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Fields[i].Value)
@Html.ValidationMessageFor(model => model.Fields[i].Value)
</div>
}
</fieldset>
}
型号:
public class Movie
{
public Movie()
{
this.Fields = new List<Field>();
}
public List<Movie> Movies { get; set; }
}
现场分类:
public class Field
{
public string Name { get; set; }
public Type Type { get; set; }
public object Value { get; set; }
}
答案 0 :(得分:2)
我相信这样的事情应该有效:
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(model => model.ID)
@{int i = 0;}
@foreach(var field in model.Fields) {
var htmlFieldName = string.Format("Fields[{0}]", i);
<div class="editor-label">
<label for="@htmlFieldName">@field.Title</label>
</div>
<div class="editor-field">
@Html.EditorFor(model => field, null, htmlFieldName)
@Html.ValidationMessage(htmlFieldName)
</div>
}
</fieldset>
}
(请注意,我编写了如何制作标签文字,因为使用实际值作为标签对我来说没有意义。)
POST应该以这样的值结束:
ID=123
Fields[0]=Jaws
Fields[1]=VeggieTales
...
...并且应该自动绑定到您的Movie模型,前提是该模型具有一个名为Fields的List<string>
。如果你的模型看起来不那样,那至少应该让你走上正确的轨道。
在评论中,您解释说您正在尝试为对象生成编辑器。这里有两个主要难点:
MVC依赖于您为EditorFor提供的lambda表达式中返回的静态类型,以确定它应该生成哪种编辑器。要覆盖此内容,您需要提供一个特定的模板名称,我的原始建议会显示您提供null
:
@Html.EditorFor(model => field.Value, field.Type.Name, htmlFieldName + ".Value")
您可能需要调整它以使其为Integer等类型提供正确的模板名称,但这应该为您提供一般的想法。
回发后,服务器无法知道Field[0]
是int
等。您可以:
根据Movie的ID在服务器端重新创建Movie对象的结构,然后遍历每个调用的字段:
TryUpdateModel((dynamic)field, string.Format("Field[{0}]", i));
可能还有其他选择,但这是我今天愿意投入的所有时间。