0

我在显示和保存导航属性时遇到了问题。使用实体框架显示和保存导航属性4 MVC3

我有3个表:

RateProfile

  • RateProfileID
  • 摘要名称

  • RateID
  • RateProfileID
  • PanelID

面板

  • PanelID
  • PanelName

我有这些和外键导航属性的每个模型(即RatesRateProfile的导航属性)。我有一个以RateProfile作为模型的编辑页面。在此页面上,我有一个PanelID的下拉菜单。下拉式过滤器显示哪些导航属性(每个panelID有28个关联的速率)。每当下拉列表发生变化时,它会发布到我的Edit方法(在继续之前保存现有数据并显示新选择的panelID的费率​​)。

我只通过ViewBag将需要的费率记录传递给我的列表。

我最初使用foreach循环

foreach(PDR.Models.Rate rate in ViewBag.Rates){ 
        @Html.HiddenFor(modelItem => rate.RateProfileID) 
        @Html.HiddenFor(modelItem => rate.RateID) 
        @Html.HiddenFor(modelItem => rate.PanelID) 

        @Html.EditorFor(modelItem => rate.Amount) 
        @Html.ValidationMessageFor(modelItem => rate.Amount) 
} 

随着foreach循环,改变下拉时PanelID,即它将与每个面板的正确率显示一切正常显示。但是,我的费率都不会与我的模型一起传递回我的控制器中的HTTPPost编辑方法。传递给我的控制器的RateProfile将在其Rates栏导航属性中有0条记录(视图中有28条记录)。

我被建议将foreach循环改为for(int i ...)循环。显然,foreach循环将所有的文本框命名为同一个东西,而普通的for循环则根据索引命名它们。

使用for(int i ...)循环时,Rates导航属性在传递给HTTPPost Edit方法时的确具有它的所有记录,并且能够根据我输入的内容更新这些记录。

但是...现在使用for(int i ...)循环,页面将不会显示基于panelID的正确记录(即使已更改,它始终显示默认panelID的记录)。更令人疯狂的是,如果我在我的观点中提出了断点,我发现正确的Rate记录正在传递给View仍然存在。我发现正确的RateID/amount等都被放入Html帮助器中,但是当页面实际显示时,它显示的是在更改下拉菜单之前存在的数据,而不是正在观看的数据,它以调试模式填充。

这里是因为从foreach循环切换到正常的循环我使用的视图代码:

@{List<PDR.Models.Rate> rates = ViewBag.rates; 
     var count = rates.Count; 
     } 
    @for (int i = 0; i < count; i++) 
    { 
        @Html.HiddenFor(modelItem => rates[i].RateProfileID) 
        @Html.HiddenFor(modelItem => rates[i].RateID) 
        @Html.HiddenFor(modelItem => rates[i].PanelID) 

        @Html.EditorFor(modelItem => rates[i].Amount) 
        @Html.ValidationMessageFor(modelItem => rates[i].Amount) 
    } 

在我看来,检查调试模式下的价值观,我知道,正确率正在传递到ViewBag.rates根据panelID。问题是,尽管我可以在调试中逐步完成它,并且观察它为上述循环中的每个速率设置了RateID,PanelIDAmount的正确值,但页面上实际显示的值总是panelID == 1的值,然后传递给我的控制器的值始终是价格的值,其中panelID == 1而不是我传递给视图的费率。

下面是编辑方法的代码。我很确定这个问题在视图中,因为rateprofile(它应该是我的视图中的模型)永远不会获得正确的导航属性。

[HttpPost] 
    public ActionResult Edit(RateProfile rateprofile, int panelID) 
    { 

     var panels = db.Panels; 
     ViewBag.PanelDropDown = new SelectList(panels, "PanelID", "PanelName", panelID); 
     ViewBag.PanelID = panelID; 

     if (ModelState.IsValid) 
     { 
      db.Entry(rateprofile).State = EntityState.Modified; 

      foreach (Rate rate in rateprofile.Rates) 
      { 
       db.Entry(rate).State = EntityState.Modified; 
      } 
      db.SaveChanges(); 
     } 
     rateprofile = db.RateProfiles.Include(a => a.Rates).Where(a => a.RateProfileID == rateprofile.RateProfileID).Single(); //reloads the current rateprofile from the db 
     PopulatePanelDropDown(rateprofile, panelID); //populates the ViewBag.rates variable 

     return View(rateprofile); 
    } 

总结:

  • foreach循环在Rates:显示一切正常基于panelID,但不会值传递给控制器​​。

  • for(int i ...)loop:只会显示panelID == 1的值,并且不会根据panelID进行更新。将保存,但只有与panelID == 1相关的记录。

+0

你不需要'for'循环,你可以使用'foreach'。诀窍是获取输入名称属性,当通过HTTP POST发送到服务器时,可以告诉默认模型绑定器如何构建复杂的viewmodel集合(for循环有助于此,但并非完全必要)。看看这些链接:http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx http://blog.stevensanderson.com/2010/01/28/编辑一个变量长度列表aspnet-mvc-2样式https://github.com/danludwig/BeginCollectionItem – danludwig 2012-07-19 04:06:53

+0

@danludwig:感谢您的链接。这是有道理的。 – 2012-07-28 23:22:34

回答

0

摸索了好几个星期,并没有找到这对我工作的任何答复后,我终于只是改变了我的HTTPpost编辑方法重定向到我的HTTPGET编辑方法,而不是返回视图。我将RateProfileID和panelID传递给我的HTTPget编辑方法,并且当面板下拉改变时,它没有任何问题显示正确的数据。