kuken kuken - 3 months ago 10
ASP.NET (C#) Question

DropDownListFor throwing error after posting the form

Why can't I get this to work?

Controller:

List<SelectListItem> list = new List<SelectListItem>() {
new SelectListItem(){ Value="1", Text="Bohuslän"},
new SelectListItem(){ Value="2", Text="Dalarna"},
new SelectListItem(){ Value="3", Text="Dalsland"}
};

SelectList surbs = new SelectList(list, "Value", "Text");
ViewBag.Dropdown = surbs;
return view();





Uses a viewmodel

public class CreateViewModel
{
public int SelectedId { get; set; }
public Add Add { get; set; }
}





View:

@Html.DropDownListFor(model => model.SelectedId, (SelectList)ViewBag.Dropdown)





Post to controller

public ActionResult Create(CreateViewModel adds)
{
if (ModelState.IsValid)
{
Add add = new Add();


.
.




Error:


The ViewData item that has the key 'SelectedId' is of type 'System.Int32' but must be of type 'IEnumerable'.

Answer

Your problem is that after postback, the value of ViewBag.Dropdown is not retained and its value is Null, so it is throwing this error. Either Set the data in ViewBag again in your HTTP POST method like this:-

public ActionResult Create(CreateViewModel adds)
    {
        if (ModelState.IsValid)
        {
            Add add = new Add();
            ------

   List<SelectListItem> list = new List<SelectListItem>() {
     new SelectListItem(){ Value="1", Text="Bohuslän"},
     new SelectListItem(){ Value="2", Text="Dalarna"},
     new SelectListItem(){ Value="3", Text="Dalsland"}
                                                        };
   SelectList surbs = new SelectList(list, "Value", "Text");
   ViewBag.Dropdown = surbs;
   return View();

You can wrap this inside a method to avoid code duplication.

Or the best approach in my opinion will be instead of passing the data in ViewBag, add a SelectList property to your ViewModel and then pass something like this:-

Updated ViewModel:-

public class CreateViewModel
{
    public int SelectedId { get; set; }
    public string Add { get; set; }
    public SelectList SurbsList { get; set; }
}

For Both Get & Post request, Bind your SurbsList like this:-

adds.SurbsList = GetSurbs();

Where, GetSurbs() is a method:-

private SelectList GetSurbs()
{
    List<SelectListItem> list = new List<SelectListItem>() 
                  {
                     new SelectListItem(){ Value="1", Text="Bohuslän"},
                     new SelectListItem(){ Value="2", Text="Dalarna"},
                     new SelectListItem(){ Value="3", Text="Dalsland"}
                  };
          return new SelectList(list, "Value", "Text");
}

And finally bind your dropdown like this:-

@Html.DropDownListFor(model => model.SelectedId, Model.SurbsList)