我在顯示和保存導航屬性時遇到了問題。使用實體框架顯示和保存導航屬性4 MVC3
我有3個表:
RateProfile
- RateProfileID
- 摘要名稱
率
- RateID
- RateProfileID
- PanelID
- 量
面板
- PanelID
- PanelName
我有這些和外鍵導航屬性的每個模型(即Rates
是RateProfile
的導航屬性)。我有一個以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,PanelID
和Amount
的正確值,但頁面上實際顯示的值總是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
相關的記錄。
你不需要'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
@danludwig:感謝您的鏈接。這是有道理的。 – 2012-07-28 23:22:34