我正在开发一个应用程序,我需要能够在运行时从数据库加载对象属性。客户希望能够向数据库添加属性并让它们显示在应用程序中。我通过为我的模型提供一个包含名称、类型和值的 Field 对象列表来实现此目的。这对于显示和编辑项目属性非常有效,但我在编辑器 View 中进行验证时遇到问题。感谢您的帮助。
我希望能够在我的编辑操作中执行此操作:
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
普通 View :
@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; }
}
最佳答案
我相信这样的事情应该有效:
@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
...
...并且应该自动绑定(bind)到您的电影模型,前提是该模型具有,例如 List<string>
名为菲尔兹。如果您的模型看起来不是这样,这至少应该让您走上正确的道路。
更新
在您的评论中,您解释说您正在尝试为对象创建一个编辑器。这里有两个主要难点:
MVC 依赖于您提供给 EditorFor 的 lambda 表达式中返回的静态类型来确定它应该生成哪种类型的编辑器。要覆盖此设置,您需要提供一个特定的模板名称,其中我最初的建议显示您提供
null
:@Html.EditorFor(model => field.Value, field.Type.Name, htmlFieldName + ".Value")
您可能需要对此进行调整,使其为 Integer 等类型提供正确的模板名称,但这应该会给您一个总体思路。
回发时,服务器无法知道
Field[0]
是int
等。您可以:提供隐藏值来指定每种类型,然后使用可以使用此信息的自定义模型绑定(bind)器来基于组合的类型和值构建每个字段。
根据电影的 ID 在服务器端重新创建电影对象的结构,然后遍历它的每个字段调用:
TryUpdateModel((dynamic)field, string.Format("Field[{0}]", i));
可能还有其他选择,但这就是我今天愿意投入的所有时间。
关于c# - 具有动态属性的 ASP.net MVC3 模型验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9419067/