Home > Blockchain >  How to solve 'There is no ViewData item of type 'IEnumerable<SelectListItem>' i
How to solve 'There is no ViewData item of type 'IEnumerable<SelectListItem>' i

Time:11-12

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.

  • Related