c# - 具有动态属性的 ASP.net MVC3 模型验证

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

我正在开发一个应用程序,我需要能够在运行时从数据库加载对象属性。客户希望能够向数据库添加属性并让它们显示在应用程序中。我通过为我的模型提供一个包含名称、类型和值的 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>名为菲尔兹。如果您的模型看起来不是这样,这至少应该让您走上正确的道路。

更新

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

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

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

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

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

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

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

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

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

关于c# - 具有动态属性的 ASP.net MVC3 模型验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9419067/

相关文章:

c# - 从颜色中去除透明度

c# - C# 中的按位赋值运算符

asp.net - 将 ASP.NET 文本框呈现为 HTML5 输入类型 "Number"

.net - 如何在fiddler中设置kerberos认证

c# - 在 SQL Server CLR 程序集中使用 Microsoft Solver Foundation

c# - 有没有容易在C#中故意引起的 "real-life"嵌套异常?

asp.net - 使用 smtp 发送邮件太慢

c# - 如何将 "&Source"添加到 DataNavigateUrlFormatString?

.net - .NET Reflector 指令的命名空间

c# - 后台线程循环和双向通信