I get error using @Html.DropDownListFor for edit session, I use it for create method is succes, but when I use in edit method is fail, the error warning like this System.InvalidOperationException: 'There is no ViewData item of type 'IEnumerable' that has the key 'roles_id'.' .
The deail file like this:
Edit.cshtml:
<div class="form-group">
@Html.LabelFor(model => model.roles, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-12">
@Html.DropDownListFor(model => model.roles_id, (SelectList)ViewBag.RolesList, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.roles_id, "", new { @class = "text-danger" })
</div>
</div>
EmployeeController.cs
// GET: Employee/Edit/{id}
public ActionResult Edit(int id)
{
AuthDBHandle dbhandle = new AuthDBHandle();
adminlteDBHandle sdb = new adminlteDBHandle();
var roles_id = sdb.GetEmployee().Find(smodel => smodel.employee_id == id).roles_id;
var roles = dbhandle.GetRoles();
ViewBag.RolesList = new SelectList(roles, "roles_id", "roles", roles_id);
return View(sdb.GetEmployee().Find(smodel => smodel.employee_id == id));
}
// POST: Employee/Edit/{id}
[HttpPost]
public ActionResult Edit(EmployeeViewModel smodel)
{
try
{
if (ModelState.IsValid)
{
adminlteDBHandle sdb = new adminlteDBHandle();
if (sdb.EditEmployee(smodel))
{
ViewBag.Message = "Edit employee is success";
ModelState.Clear();
return RedirectToAction("Index");
}
return View();
}
return View();
}
catch
{
return View();
}
}
EmployeeViewModel.cs
namespace adminlte.Models
{
public class EmployeeViewModel
{
[Display(Name = "Employee Id")]
public int employee_id { get; set; }
[Required(ErrorMessage = "Fullname is required.")]
public string fullname { get; set; }
[Required(ErrorMessage = "Address is required.")]
[DataType(DataType.MultilineText)]
public string address { get; set; }
public string roles { get; set; }
[Required(ErrorMessage = "Role ID is required.")]
public int roles_id { get; set; }
[Required(ErrorMessage = "Email is required.")]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string email { get; set; }
public string password { get; set; }
}
}
I don't know why, I try to look for an example but fail all, please help me to solve this problem.
Thanks.
CodePudding user response:
Data you put in the ViewBag
is not persisted between requests. When you try to display your view again, you need to repopulate the ViewBag
items.
I generally extract the code to populate the lookups to a separate method, which avoids duplication.
Eg:
private void PopulateLookups(EmployeeViewModel vm)
{
AuthDBHandle dbhandle = new AuthDBHandle();
var roles = dbhandle.GetRoles();
ViewBag.RolesList = new SelectList(roles, "roles_id", "roles", vm.roles_id);
}
// GET: Employee/Edit/{id}
public ActionResult Edit(int id)
{
adminlteDBHandle sdb = new adminlteDBHandle();
var employee = sdb.GetEmployee().Find(smodel => smodel.employee_id == id);
if (model == null) return RedirectToAction("Index");
var vm = new EmployeeViewModel
{
employee_id = employee.employee_id,
fullname = employee.fullname,
address = employee.address,
roles = employee.roles,
roles_id = employee.roles_id,
email = employee.email,
password = employee.password, // WARNING!
};
PopulateLookups(vm);
return View(vm);
}
// POST: Employee/Edit/{id}
[HttpPost]
public ActionResult Edit(EmployeeViewModel vm)
{
try
{
if (ModelState.IsValid)
{
adminlteDBHandle sdb = new adminlteDBHandle();
if (sdb.EditEmployee(vm))
{
return RedirectToAction("Index");
}
}
PopulateLookups(vm);
return View();
}
catch
{
PopulateLookups(vm);
return View();
}
}
NB: Based on your column names, you appear to be storing the employees' passwords in plain text. Don't do that! Store a salted hash of the password, using multiple iterations of a cryptographically-secure one-way hashing algorithm.