TyForHelpDude
TyForHelpDude

Reputation: 5002

how to bind selectlistitem value in dropdownlist to string property in model

This is how I populate dropdownlist and create html element;

AccountController:

      public ActionResult Index()
        {
            ViewBag.Towns = new SelectList(_skrsService.GetTowns(), "Value", "Text", 1);
            return View();
        }
...

public List<SelectListItem> GetTowns()
        {
            var list = UnitOfWork.Repository<SkrsIl>().OrderBy(x => x.Adi).Select(x => new SelectListItem()
            {
                Text = x.Adi,
                Value = x.Kodu.ToString()
            }).ToList();
            return list;
        }

Login.cshtml(Hometown is string field in model bindned to login view page):

 @Html.DropDownListFor( x => x.Hometown, ((SelectList)ViewBag.Towns), new {  @class = "form-control", placeholder = "Doğum Yeri" })

I expected this to work but getting error, message:

"The ViewData item that has the key 'Hometown' is of type 'System.String' but must be of type 'IEnumerable<SelectListItem>'."

how can I make it work properly? I just expected selectem item value to 'Hometown' property

Upvotes: 1

Views: 1772

Answers (1)

user3559349
user3559349

Reputation:

The error means that that ViewBag.Towns is null. When the 2nd parameter (IEnumerable<SelectListItem> selectList) is null, the method expects the first parameter to be typeof IEnumerable<SelectListItem>.

Since you have assigned it in the GET method, this is almost certainly happening when you submit your form and have returned the view but have not repopulated the value of ViewBag.Towns as you did in the GET method.

As a side note, using new SelectList() is pointless extra overhead - it just creates another IEnumerable<SelectListItem> based on the first one. In addition, the 4th parameter of the SelectList constructor is ignored when you bind to a model property - internally the method builds a new IEnumerable<SelectListItem> and sets the Selected property based on the value of the property your binding to.

Your controller code should be

public ActionResult Index()
{
    ViewBag.Towns = _skrsService.GetTowns();
    return View(); // ideally you should be returning a model
}
[HttpPost]
public ActionResult Index(YourModel model)
{
    if (!ModelState.IsValid)
    {
        ViewBag.Towns = _skrsService.GetTowns(); // re-populate the SelectList
        return View(model);
    }
    // save and redirect
}

But preferably you should be using a view model containing a property for the select list rather than ViewBag.

Upvotes: 1

Related Questions