I have a many-to-many
field in Menu model named Roles
, i'm trying to create a 'create' view for the model.
我在Menu模型中有一个名为Roles的多对多字段,我正在尝试为模型创建一个“创建”视图。
my create action methods:
我的创建动作方法:
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);
}
my view(Create.cshtml):
我的观点(Create.cshtml):
<div class="editor-label">
@Html.LabelFor(model => model.Roles, "Roles")
</div>
<div class="editor-field">
@Html.ListBox("Roles")
@Html.ValidationMessageFor(model => model.Roles)
</div>
how to fix it? I'm getting the following error:
怎么解决?我收到以下错误:
The ViewData item that has the key '' is of type '' but must be of type 'IEnumerable<SelectListItem>'
具有键''的ViewData项的类型为'',但必须是'IEnumerable
2 个解决方案
#1
4
Well, the error message is rather clear, you nead a IEnumerable<SelectListItem>
好吧,错误信息相当清楚,你有一个IEnumerable
So change your ViewBag.Roles definition from
所以改变你的ViewBag.Roles定义
new SelectList(_db.UserRoles.ToList(), "Id", "Name");
to
至
_db.UserRoles.ToList().Select(m => new SelectListItem { Value=m.Id, Text=m.Name});
Edit
编辑
In your view :
在你看来:
@Html.ListBox("Roles", (IEnumerable<SelectListItem>)ViewBag.Roles)
Edit2
EDIT2
You have a model binding problem
你有一个模型绑定问题
In your view
在你看来
@Html.ListBox("selectedRoles", (IEnumerable<SelectListItem>)ViewBag.Roles)
in your Post Action, try to add a new parameter :
在你的Post Action中,尝试添加一个新参数:
[HttpPost]
public ActionResult Create(Menu menu, int[] selectedRoles)
and treat each selected role "manually" in your action code.
并在您的操作代码中“手动”处理每个选定的角色。
EDIT
编辑
ViewModel sample (not working as is) In your view, you need
ViewModel示例(不按原样工作)在您的视图中,您需要
-
a DropDownList (ParentMenuId)
DropDownList(ParentMenuId)
-
a ListBox (RoleIDs)
ListBox(RoleIDs)
-
the result of this listBox (model binding for the post action)
这个listBox的结果(post动作的模型绑定)
-
other properties of the Menu class (maybe not all)
Menu类的其他属性(可能不是全部)
The idea would be to create a
想法是创建一个
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;}
}
then your get Action would be
然后你的行动将是
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);
}
your view would have MenuViewModel... as 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>
then your POST action would become
然后你的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 :
Pro ViewModel:
-
you're just using the properties you need.
你只是使用你需要的属性。
-
you don't need ViewBag (which is nice to avoid : it's dynamic, not strongly typed, so... hard to test, refactoring problems, etc.)
你不需要ViewBag(这是很好的避免:它是动态的,不是强类型的,所以......很难测试,重构问题等等)
-
everything is in your view's model
一切都在你视图的模型中
Cons ViewModel :
缺点ViewModel:
- you have to map your Model to your ViewModel in the get action, and map from ViewModel to Model in post action, but... it's worse the price !
- 你必须在get动作中将你的Model映射到ViewModel,并在post动作中从ViewModel映射到Model,但是......它的价格更差!
#2
-1
I was create same project but i don't get that error.
我是创建相同的项目,但我没有得到该错误。
It seems model of listbox was bound to another type, try to specify explicitly viewbag model like this:
似乎列表框的模型绑定到另一个类型,尝试明确指定viewbag模型,如下所示:
@Html.ListBox("Roles",ViewBag.Roles as SelectList)
And in [HttpPost] method try to add ViewBag.Roles which exists in Create - get method, like this:
并在[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);
}
#1
4
Well, the error message is rather clear, you nead a IEnumerable<SelectListItem>
好吧,错误信息相当清楚,你有一个IEnumerable
So change your ViewBag.Roles definition from
所以改变你的ViewBag.Roles定义
new SelectList(_db.UserRoles.ToList(), "Id", "Name");
to
至
_db.UserRoles.ToList().Select(m => new SelectListItem { Value=m.Id, Text=m.Name});
Edit
编辑
In your view :
在你看来:
@Html.ListBox("Roles", (IEnumerable<SelectListItem>)ViewBag.Roles)
Edit2
EDIT2
You have a model binding problem
你有一个模型绑定问题
In your view
在你看来
@Html.ListBox("selectedRoles", (IEnumerable<SelectListItem>)ViewBag.Roles)
in your Post Action, try to add a new parameter :
在你的Post Action中,尝试添加一个新参数:
[HttpPost]
public ActionResult Create(Menu menu, int[] selectedRoles)
and treat each selected role "manually" in your action code.
并在您的操作代码中“手动”处理每个选定的角色。
EDIT
编辑
ViewModel sample (not working as is) In your view, you need
ViewModel示例(不按原样工作)在您的视图中,您需要
-
a DropDownList (ParentMenuId)
DropDownList(ParentMenuId)
-
a ListBox (RoleIDs)
ListBox(RoleIDs)
-
the result of this listBox (model binding for the post action)
这个listBox的结果(post动作的模型绑定)
-
other properties of the Menu class (maybe not all)
Menu类的其他属性(可能不是全部)
The idea would be to create a
想法是创建一个
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;}
}
then your get Action would be
然后你的行动将是
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);
}
your view would have MenuViewModel... as 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>
then your POST action would become
然后你的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 :
Pro ViewModel:
-
you're just using the properties you need.
你只是使用你需要的属性。
-
you don't need ViewBag (which is nice to avoid : it's dynamic, not strongly typed, so... hard to test, refactoring problems, etc.)
你不需要ViewBag(这是很好的避免:它是动态的,不是强类型的,所以......很难测试,重构问题等等)
-
everything is in your view's model
一切都在你视图的模型中
Cons ViewModel :
缺点ViewModel:
- you have to map your Model to your ViewModel in the get action, and map from ViewModel to Model in post action, but... it's worse the price !
- 你必须在get动作中将你的Model映射到ViewModel,并在post动作中从ViewModel映射到Model,但是......它的价格更差!
#2
-1
I was create same project but i don't get that error.
我是创建相同的项目,但我没有得到该错误。
It seems model of listbox was bound to another type, try to specify explicitly viewbag model like this:
似乎列表框的模型绑定到另一个类型,尝试明确指定viewbag模型,如下所示:
@Html.ListBox("Roles",ViewBag.Roles as SelectList)
And in [HttpPost] method try to add ViewBag.Roles which exists in Create - get method, like this:
并在[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);
}