【问题标题】:Validation on ASP.net MVC3 Model with Dynamic Properties使用动态属性验证 ASP.net MVC3 模型
【发布时间】:2012-03-14 05:07:30
【问题描述】:

我正在开发一个应用程序,我需要能够在运行时从数据库加载对象属性。客户希望能够将属性添加到数据库并让它们显示在应用程序中。我通过给我的模型一个包含名称、类型和值的 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; }
} 

【问题讨论】:

  • 你能指定你的模型是什么样子的吗?

标签: c# asp.net .net asp.net-mvc-3 web-applications


【解决方案1】:

我相信这样的事情应该可行:

@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&lt;string&gt;。如果您的模型看起来不是那样,这至少应该让您走上正轨。

更新

在您的评论中,您解释说您正在尝试为 object 生成一个编辑器。这里有两个主要的难点:

  1. MVC 依赖于您提供给 EditorFor 的 lambda 表达式中返回的静态类型来确定它应该生成哪种类型的编辑器。要覆盖它,您需要提供一个特定的模板名称,我的原始建议显示您提供null

     @Html.EditorFor(model => field.Value, field.Type.Name, htmlFieldName + ".Value")
    

    您可能需要对其进行调整,以使其为 Integer 等类型提供正确的模板名称,但这应该可以为您提供总体思路。

  2. 回发时,服务器无法知道Field[0]int 等。您可以:

    1. 提供隐藏值来指定每种类型,然后使用可以使用此信息的自定义模型绑定器基于组合的类型和值构建每个字段。

    2. 根据电影的 ID 在服务器端重新创建电影对象的结构,然后遍历它的每个字段调用:

       TryUpdateModel((dynamic)field, string.Format("Field[{0}]", i));
      

可能还有其他选择,但这就是我今天愿意投入的所有时间。

【讨论】:

  • @Manas:EditorFor 根本不是 LINQ 方法,虽然我不喜欢使用 EditorFor 来完成我在这里所做的事情,但这种语法可以完成这项工作。如果您找到更好的方法,我很乐意更改我的答案。
  • 如果 Fields 是 List 则有效。问题在于 Fields 是一个 List,其中包含一个 Name(字符串)、一个 Type(类型)和一个 Value(对象)。当我@Html.EditorFor(model => field.Value, null, htmlFieldName) 时,它不会呈现任何内容。如果我将 .Value 更改为字符串或其他原始类型,它会渲染一些东西。
  • @user1229080:为了确保人们给您最好的答案,请按照 Manas 的要求,使用有关您的模型的信息更新您的问题。
  • 我的问题有关于模型的信息。我只是在上面的评论中重复了一遍。
  • @StriplingWarrior:我实际上不需要自定义模板。现在的问题是,如果我传入@Html.EditorFor(model =&gt; field.Value, null, htmlFieldName),验证将不起作用,但如果我传入int fieldValue = field.Value 然后@Html.EditorFor(fieldValue, field.Type.Name, htmlFieldName,它确实有效。当然我可以验证这一点,但它没有绑定到模型,因为它只是值的副本。我制作了一个自定义编辑器模板,以确保 fieldValue 和 field.Value 都作为整数处理,并且它们是。我想我应该为这个问题打开一个新问题。
猜你喜欢
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多