I've been playing with this HTML Helper for awhile now, following all sorts of examples which in theory accomplish the same end result. However, I can't seem to produce the end result.
Maybe someone can see what I'm doing wrong before I go back to iterating out select options with a foreach. It would be nice to lock in how this helper works, less code than a select with a foreach().
Edit controller:
public ActionResult Edit(string id)
{
if (id != "")
{
UserViewModel user = (from u in db.Users.Where(u => u.Id.Equals(id))
from ur in u.Roles
join r in db.Roles on ur.RoleId equals r.Id
select new UserViewModel
{
UserId = u.Id,
DisplayName = u.DisplayName,
Role = r.Name,
RoleId = r.Id
}
).FirstOrDefault();
//Select List items for select list
var roles = db.Roles.Select(r => new SelectListItem { Value = r.Id, Text = r.Name });
//select list with selected value
user.Roles = new SelectList(roles,"Value", "Text", user.RoleId);
return View(user);
}
return View();
}
View;
<div class="form-group">
@Html.LabelFor(model => model.Role, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Role, Model.Roles, null, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Role, "", new { @class = "text-danger" })
</div>
</div>
Your code
var roles = db.Roles.Select(r => new SelectListItem { Value = r.Id, Text = r.Name });
creates IEnumerable<SelectListItem>
.
user.Roles = new SelectList(roles,"Value", "Text", user.RoleId);
just creates another identical IEnumerable<SelectListItem>
from it so its just pointless extra overhead and since your binding to a property in your model, the last paramater (user.RoleId
) is ignored and also pointless
It should be just
user.Roles = db.Roles.Select(r => new SelectListItem { Value = r.Id, Text = r.Name });
When your create this SelectList
you setting the value to the Id
property of Role
but you then attempting to bind to the Role
property of UserViewModel
instead of the RoleId
property. Because the value of Role
will not match one of the option values the first option in the dropdownlist will always be selected (because something has to be).
Change the code in your view to
@Html.DropDownListFor(model => model.RoleId, Model.Roles, null, new { @class = "form-control" })
If the value of RoleId
matches one of the option values, then it will be selected.
Side note: your Role
property in your view model seems unnecessary, as does the need to create a join to the Roles
table in your query.