2011-07-23 68 views
4

所以我有这个演示项目几乎完全工作。帮助asp.net mvc的嵌套模型绑定

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

的问题是,当我提出的任务是填充除了虚拟财产项目一切形式......所以错误我得到它是

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

这里是我的断点调试结果的PIC

enter image description here

请帮助。

UPDATE:

我已经改变了我的控制器行动,这

[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); 
     } 

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

+0

可以直接调用'db.Projects.Single(P =>页。 ID == project.ID);'没有'Where'。 –

回答

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--> 

以上,并且会为集合中的每个任务产生在收集的第一项任务和类似HTML生成的HTML近似。唯一的区别是索引将在所有输入的名称属性中增加,即Tasks[1].Name,Tasks[1].ProjectID等。此部分将实际绑定到ProjectCollection<Task> Tasks属性,但您可以看到详细信息部分中没有任何输入,如

<input type="whatever" name="Tasks[0].Project.ProjectID" .../> 
<input type="whatever" name="Tasks[0].Project.Name" ..../> 

ModelBinder的需要与适当的命名约定输入元素的值绑定到的动作方法参数的所有属性。出于测试目的,你可以在形式inlude在你的编辑器模板这两条线路的任务

他们
@Html.TextBoxFor(x=>x.Project.ID) 
@Html.TextBoxFor(x=>x.Project.Name) 

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

+0

你是对的。我不想为表单中的每个任务再次输入项目信息...我使用EF ...真的很奇怪,像这样的简单任务没有干净的解决方案 – ignaciofuentes

+0

EF我相信如果你附加这个实体到数据库实体,你不必拥有项目属性填充。 –

+0

林不知道我明白你的意思....你会介意张贴代码示例? – ignaciofuentes