帮助asp.net mvc嵌套模型绑定

时间:2011-07-23 06:28:41

标签: asp.net-mvc entity-framework nested-forms model-binding

所以我让这个演示项目几乎完全正常工作。

public class Project
    {
        public int ID { get; set; }
        [Required]
        public string Name { get; set; }
        public virtual ICollection<Task> Tasks { get; set; }

    }

    public class Task
    {
        public int ID { get; set; }
        [Required]
        public string Name { get; set; }
        public int ProjectID { get; set; }

        public virtual Project Project { get; set; }

    }

控制器

public ActionResult Edit(int id)
        {           
            var project = db.Projects.Where(p=>p.ID==id).Single();
            return View(project);
        }

        [HttpPost]
        public ActionResult Edit(Project project)
        {
            if (ModelState.IsValid)
            {
                var dbProject = db.Projects.Where(p => p.ID == project.ID).Single();

                UpdateModel(dbProject);
                db.SaveChanges();                
                TempData["Success"] = "Modelo Valido";
            }
            return RedirectToAction("Index");
        }

查看//为项目强烈输入

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Project</legend>
        @Html.HiddenFor(model => model.ID)
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <h1>Tasks</h1>
        @Html.EditorFor(m => m.Tasks)
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

EditorTemplate

@model MvcApplication2.Models.Task
<span>Task</span>
<br />
    @Html.LabelFor(m => m.Name)
    @Html.EditorFor(m => m.Name)
    @Html.HiddenFor(m => m.ID)
    @Html.HiddenFor(m => m.ProjectID)
    @Html.ValidationMessageFor(m => m.Name)

视图显示此

enter image description here

问题在于,当我提交表单时,任务将填充除虚拟Project属性之外的所有内容...所以我得到的错误是

  

操作失败:无法更改关系,因为   一个或多个外键属性是不可为空的。当一个   改变了关系,相关的外键属性是   设置为空值。如果外键不支持空值,   必须定义新的关系,外键属性必须是   分配了另一个非空值,或者不相关的对象必须是   删除。

这是我的调试断点结果的图片

enter image description here

请帮助。

更新

我已将控制器操作更改为此

[HttpPost]
        public ActionResult Edit(Project project)
        {
            if (ModelState.IsValid)
            {
                db.Entry(project).State = EntityState.Modified;
                db.SaveChanges();                
                TempData["Success"] = "Modelo Valido";
                return RedirectToAction("Index");
            }
            return View(project);
        }

它仍然无法正常工作。 现在,对项目名称所做的更改将在数据库中正确更新。但完全忽略对任何任务名称所做的更改。

2 个答案:

答案 0 :(得分:4)

我相信@Html.EditorFor(m => m.Tasks)正在生成html(大约)

<label>Name</label>
<input type="text" name="Tasks[0].Name" id="auto-gen-id"/>
<input type="hidden" name="Tasks[0].ID" id = "auto-gen-id"/>
<input type="hidden" name="Tasks[0].ProjectID" id = "auto-gen-id"/>
<!--html for validation span-->

以上是为Collection中的第一个Task生成的近似html,将为集合中的每个任务生成类似的html。唯一的区别是索引将在所有输入的名称属性中递增,即Tasks[1].NameTasks[1].ProjectID等。此部分实际上将绑定到Collection<Task> Tasks的{​​{1}}属性但您可以看到详细部分你没有任何输入,如

Project

Modelbinder需要具有适当命名约定的输入元素,以将值绑定到操作方法参数的所有属性。出于测试目的,您可以在编辑器模板中为任务

添加这两行
<input type="whatever" name="Tasks[0].Project.ProjectID" .../>
<input type="whatever" name="Tasks[0].Project.Name" ..../>

在表单中为它们输入正确的值,您将使用这些值填充Task的Project属性。但可能不是你想要的,即两次输入项目信息,这可能不需要(如果你使用Linq sql肯定不需要)。当您调用ORM将实体附加到数据库实体时,它将知道当前任务属于哪个项目元素 旁注:当您遇到模型绑定问题时,请始终注意生成的html。只要您使用默认的模型绑定器,生成的html将指示哪些表单值将映射到模型的哪些属性。如果您在示例中拥有主要详细类型的场景,那就变得尤为重要。

答案 1 :(得分:1)

我找到了一种让这种方法发挥作用的方法,但我对这种方法并不完全满意。

请参阅此问题,了解如何重构当前代码以了解我当前的情况(希望暂时执行此操作)

Help improving (refactoring) my code. Automapper - EF - asp.net mvc-3

相关问题