我在菜单模型中有一个名为many-to-many
的{{1}}字段,我正在尝试为模型创建一个“创建”视图。
我的创建动作方法:
Roles
我的观点( Create.cshtml ):
public ActionResult Create()
{
ViewBag.ParentMenuId = new SelectList(_db.Menus, "Id", "Name");
ViewBag.Roles = new SelectList(_db.UserRoles.ToList(), "Id", "Name");
return View();
}
[HttpPost]
public ActionResult Create(Menu menu)
{
if (ModelState.IsValid)//the state is always **invalid**
{
_db.Menus.Add(menu);
_db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ParentMenuId = new SelectList(_db.Menus, "Id", "Name", menu.ParentMenuId);
return View(menu);
}
如何解决?我收到以下错误:
<div class="editor-label">
@Html.LabelFor(model => model.Roles, "Roles")
</div>
<div class="editor-field">
@Html.ListBox("Roles")
@Html.ValidationMessageFor(model => model.Roles)
</div>
答案 0 :(得分:4)
嗯,错误信息很清楚,你有一个IEnumerable<SelectListItem>
因此,请从
更改ViewBag.Roles定义new SelectList(_db.UserRoles.ToList(), "Id", "Name");
到
_db.UserRoles.ToList().Select(m => new SelectListItem { Value=m.Id, Text=m.Name});
修改
在您看来:
@Html.ListBox("Roles", (IEnumerable<SelectListItem>)ViewBag.Roles)
Edit2
您有模型绑定问题
在你看来
@Html.ListBox("selectedRoles", (IEnumerable<SelectListItem>)ViewBag.Roles)
在你的Post Action中,尝试添加一个新参数:
[HttpPost]
public ActionResult Create(Menu menu, int[] selectedRoles)
并在您的操作代码中“手动”处理每个所选角色。
修改强>
ViewModel示例(不按原样工作) 在您看来,您需要
DropDownList(ParentMenuId)
ListBox(RoleIDs)
此listBox的结果(后期操作的模型绑定)
Menu类的其他属性(可能不是全部)
这个想法是创建一个
public class MenuViewModel
{
public IEnumerable<SelectListItem> ParentMenuList {get;set;}//a dropDown
public IEnumerable<SelectListItem> RoleList {get;set;}//a listBox
public string Name {get;set;}//the menu name //the menu name
public List<int> SelectedRoles {get;set;}
}
然后你的行动将是
public ActionResult Create()
{
var model = new MenuViewModel();
model.ParentMenuList = new SelectList(_db.Menus, "Id", "Name");
model.RoleList = new SelectList(_db.UserRoles.ToList(), "Id", "Name");
return View(model);
}
您的视图会将MenuViewModel ...作为模型
@model MenuViewModel
//your other code
//the listbox
<div class="editor-label">
@Html.LabelFor(model => model.SelectedRoles, "Roles")
</div>
<div class="editor-field">
@Html.ListBoxFor(m => m.SelectedRoles, Model.RoleList)
@Html.ValidationMessageFor(model => model.Roles)
</div>
然后您的POST操作将变为
[HttpPost]
public ActionResult Create(MenuViewModel model)
{
if (ModelState.IsValid)
{
var menu = new Menu {Name = model.Name };//for example
menu.Roles = _db.UserRoles.Where(rl => model.SelectedRoles.Contains(rl.Id)).ToList();
_db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
Pro ViewModel:
您只是使用了所需的属性。
你不需要ViewBag(这是很好的避免:它是动态的,不是强类型的,所以......很难测试,重构问题等等。)
一切都在您视图的模型中
Cons ViewModel:
答案 1 :(得分:-1)
我创建的是同一个项目,但我没有收到该错误。
似乎列表框的模型绑定到另一个类型,尝试明确指定viewbag模型:
@Html.ListBox("Roles",ViewBag.Roles as SelectList)
在[HttpPost]方法中尝试添加存在于Create - get方法中的ViewBag.Roles,如下所示:
[HttpPost]
public ActionResult Create(Menu menu)
{
if (ModelState.IsValid)//the state is always **invalid**
{
_db.Menus.Add(menu);
_db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ParentMenuId = new SelectList(_db.Menus, "Id", "Name", menu.ParentMenuId);
ViewBag.Roles = new SelectList(_db.UserRoles.ToList(), "Id", "Name");
return View(menu);
}