0

I have a people controller for user management and I'm trying to figure out how to get the dropdown choice when the user submits from the edit page. Whenever I hit submit on the page, none of the values from the view model seem to carry through to the post. I can't get the value they chose from the drop down to set the role.

See view model below:

public class PersonViewModel
{
    public int PersonId { get; set; }
    [Display(Name = "Full Name")]
    public string FullName { get; set; }
    public string Email { get; set; }
    [Display(Name = "Current Role")]
    public string SetRole { get; set; }
    public List<RoleListViewModel> Roles { get; set; }
}

See controller edit functions below:

// GET: People/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Person person = db.people.Find(id);
        if (person == null)
        {
            return HttpNotFound();
        }
        PersonViewModel pvm = new PersonViewModel();
        List<IdentityRole> roles = adb.Roles.ToList();
        var rlvm = new List<RoleListViewModel>();
        roles.ForEach(x => rlvm.Add(new RoleListViewModel { RoleId = x.Id, RoleName = x.Name }));
        pvm.PersonId = person.PersonId;
        pvm.FullName = person.FirstName + " " + person.LastName;
        pvm.Email = person.Email;
        pvm.Roles = rlvm;
        ViewBag.RoleList = new SelectList(rlvm, "RoleName", "RoleName", person.CurrentRole);

        return View(pvm);
    }

    // POST: People/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(PersonViewModel pvm)
    {
        if (ModelState.IsValid)
        {
            db.Entry(pvm).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        var usr = new AccountController();
        var pers = db.people.Where(x => x.PersonId == pvm.PersonId).FirstOrDefault();
        usr.UserManager.AddToRoleAsync(pers.NetId, /* their choice should go here but how? */);
        db.SaveChanges();


        return View(pvm);
    }

Here is the cshtml:

    <div class="form-group">
        @Html.LabelFor(model => model.Roles, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="form-control-static">
            @Html.DropDownList("RoleList", null, new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.Roles, "", new { @class = "text-danger" })
        </div>
    </div>
Nathan McKaskle
  • 2,926
  • 12
  • 55
  • 93
  • Your binding to a property named `RoleList` which does not exist in your model. I assume you want `@Html.DropDownListFor(m => m.SetRole, (SelectList)ViewBag.RoleList)` And then you need to delete the last parameter in the `SelectList`constructor (if you want to have an option selected then you need to set the value of `SetRole`). And you label and validation message should be binding to `SetRole` not `Roles`. And since you have a view model, `Roles` should be typeof `Enumerable` and get rid of `VIewBag`. –  Feb 14 '17 at 21:37
  • I suggest you study the code [here](http://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) –  Feb 14 '17 at 21:37

1 Answers1

1

Make a variable in your View Model to store the selected value and then in the view use

@Html.DropDownListFor(m => m.SelectedRoleVariable, RolesSelectList, new { @class = "form-control" });
Barry O'Kane
  • 1,189
  • 7
  • 12
  • He could just use the SetRole variable since he's probably setting the current role – Fran Feb 14 '17 at 17:12
  • Where does that RolesSelectList come from? I assume it's a selectlist but I created mine in the controller and assigned it to ViewBag.RoleList – Nathan McKaskle Feb 14 '17 at 18:46
  • I created a new selectlist in the cshtml using model.rlvm but when I hit submit, for some reason the pvm.Email property is null. Why? I debug and I can see person.Email is set so it makes no sense that it would be null. – Nathan McKaskle Feb 14 '17 at 19:21
  • `RolesSelectList` was just a made up name to give you an idea of what you're looking at. As for person.Email, if the value is held in the view model when it's created but you don't have a field in the view for it then it'll be null when you POST to the controller. You need to have something like `@Html.HiddenFor(m => m.Email)` to store the value. – Barry O'Kane Feb 15 '17 at 09:29