我有一个我不明白的问题,似乎没有一个简单的方法来调试问题。我确信这很简单。
@model StartStop.ServiceResources.UserSettings
我的MVC3视图绑定了一个特定的模型;
public class Setting
{
public Int64 SettingID { get; set; }
public Int64 UserID { get; set; }
public int PreferenceType { get; set; }
public string PreferenceName { get; set; }
public bool PreferenceBool { get; set; }
public int PreferenceInt { get; set; }
public string PreferenceString { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
}
public class UserSettings
{
public Int64 UserID { get; set; }
public List<Setting> Settings { get; set; }
}
视图列出了代表列表的复选框;
@using (Html.BeginForm("ManageAccount","Account", FormMethod.Post))
{
<table class="tbl" cellspacing="0">
<tr>
<th>Preference</th>
<th>Setting</th>
</tr>
@if (Model != null)
{
foreach (var item in Model.Settings.ToList())
{
<tr>
<td>@item.PreferenceName
</td>
<td>
@if (item.PreferenceType == 2)
{
@Html.CheckBoxFor(modelItem => item.PreferenceBool)
}
</td>
</tr>
}
}
</table>
<input type="submit" value="Save Changes" class="action medium" />
}
一切都很好,我将数据加载到视图中,呈现视图并获取正确的设置。但是,当我在底部发帖时,视图模型返回null!我不确定为什么......
[HttpPost]
[Authorize]
public ActionResult ManageAccount(StartStop.ServiceResources.UserSettings model)
{
if (ModelState.IsValid)
{
foreach (StartStop.ServiceResources.Setting oSetting in model.Settings)
{
StartStop.Helpers.UserPreferences.SaveUserSetting(oSetting);
}
}
return View(model);
}
有人可以帮忙吗?
答案 0 :(得分:5)
问题出在您视图的以下一行:
@Html.CheckBoxFor(modelItem => item.PreferenceBool)
我看到人们经常在他们的视图中编写以下lambda表达式modelItem => item.SomeProperty
,并询问为什么模型绑定器没有正确地绑定其视图模型上的集合属性。
这不会为复选框生成正确的名称,以便默认模型绑定器能够重新创建Settings集合。我建议你阅读following blog post以更好地理解模型绑定器所期望的正确格式。
试试这样:
@model StartStop.ServiceResources.UserSettings
@using (Html.BeginForm("ManageAccount", "Account", FormMethod.Post))
{
<table class="tbl" cellspacing="0">
<tr>
<th>Preference</th>
<th>Setting</th>
</tr>
@if (Model != null)
{
for (var i = 0; i < Model.Settings.Count; i++)
{
<tr>
<td>@Model.Settings[i].PreferenceName</td>
<td>
@if (Model.Settings[i].PreferenceType == 2)
{
@Html.CheckBoxFor(x => x.Settings[i].PreferenceBool)
}
</td>
</tr>
}
}
</table>
<input type="submit" value="Save Changes" class="action medium" />
}
话虽如此,我建议你使用编辑器模板,如下:
@using (Html.BeginForm("ManageAccount","Account", FormMethod.Post))
{
<table class="tbl" cellspacing="0">
<tr>
<th>Preference</th>
<th>Setting</th>
</tr>
@if (Model != null)
{
@Html.EditorFor(x => x.Settings)
}
</table>
<input type="submit" value="Save Changes" class="action medium" />
}
然后定义一个自定义编辑器模板,该模板将自动为Settings
集合(~/Views/Shared/EditorTemplates/Setting.cshtml
)的每个元素呈现:
@model StartStop.ServiceResources.Setting
<tr>
<td>@Model.PreferenceName</td>
<td>
@if (Model.PreferenceType == 2)
{
@Html.CheckBoxFor(x => x.PreferenceBool)
}
</td>
</tr>
此外,我在此表单中可以看到的唯一输入字段是复选框,该复选框绑定到模型上的PreferenceBool
属性。因此,在POST控制器操作中,您将初始化Settings列表属性,但不希望在此Setting
类中找到其他属性的任何值,除非您在表单中包含它们的输入字段(以及更多)正是在我所展示的编辑器模板中。