Reputation: 4266
My dropDown list doesn't want to have default value!
<div class="form-group">
@Html.LabelFor(model => model.unit, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(x => x.unit.id, selectUnit)
@Html.ValidationMessageFor(model => model.unit.id, "", new { @class = "text-danger" })
</div>
</div>
Show me the right list but none is selected.
I get my SelectList by using ViewBag:
@{
IEnumerable<SelectListItem> selectUnit = ViewBag.Unit;
}
When I breakpoint the cshtml, Model.unit.id is 4 and selectUnit have one item with 4 as value.
When I do
@selectUnit.Where(x => x.Value == Model.unit.id.ToString()).First().Text
it selects the right text value!
Lats think: this is my Unit model:
public class Unit
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public IList<Unit> children { get; set; }
}
Thanks in advance folks, I'm becoming crasy
EDIT:
public class ModelPassedTroughTheView
{
...
public Unit unit { get; set; }
}
EDIT 2: Full code:
Edit page: @model BE.DealerGroupSAP
@{
ViewBag.Title = Resources.Admin.DealerGroup_Edit;
IEnumerable<SelectListItem> selectUnit = ViewBag.Unit;
}
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>@ViewBag.Title</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.id)
<div class="form-group">
@Html.LabelFor(model => model.unit, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(x => x.unit.id, selectUnit)
@Html.ValidationMessageFor(model => model.unit.id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="@Resources.Global.Save_Edits" class="btn btn-default" />
</div>
</div>
</div>
}
Model passer trough view:
public class DealerGroupSAP
{
public int id { get; set; }
public Unit unit { get; set; }
}
Unit object:
public class Unit
{
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public IList<Unit> children { get; set; }
}
Controller's content:
ViewBag.Unit = GetUnits();
return View(BL.AnomalyBL.GetAllSAPResponsible(id));
Upvotes: 2
Views: 77
Reputation:
The issue is that your model has a property named unit
and your also passing the SelectList
view a ViewBag
property named Unit
(the model binding features of MVC are case insensitive.
Change the name of the ViewBag
property to (say)
ViewBag.UnitList = GetUnits();
and in the view
@{ IEnumerable<SelectListItem> selectUnit = ViewBag.UnitList }
and the correct option will be selected.
To explain what is happening internally:
The DropDownListFor()
method determines the defaultValue
(selected item) by first checking values in ModelState
(which in your case do not exist), then checking ViewData
. Because ViewData
contains a key/value pair for Unit
, which is IEnumerable<SelectListItem>
and does not contain a property id
, the defaultValue
is null
and the method uses the IEnumerable<SelectListItem>
you passed to the view to build the <option>
elements, none of which have a Selected = true
value, so the first option is selected because something has to be.
Changing the ViewBag
property to to (say) UnitList
means the method does not find a matching key for unit
in ViewData
and now inspects the model for unit.id
, which exists, and sets defaultValue = 4
. Because defaultValue
is not null
, a new IEnumerable<SelectListItem>
is generated internally, and the corresponding SelectListItem
has its Selected
property set to true
.
To understand how this all works in detail, you can inspect the source code for SelectExtensions - in particular the private static MvcHtmlString SelectInternal()
method.
As a final note, this is just one more reason why you should always use a view model.
Upvotes: 2