Question

I am trying to get a drop down list to work but its not working for me. This application is mainly a festival based application where you can add a festival along with your events. The error I am getting is on line:

@Html.DropDownList("towns", (IEnumerable<SelectListItem>)ViewData["Town"], new{@class = "form-control", @style="width:250px" })

This is the error I get:

There is no ViewData item of type 'IEnumerable' that has the key 'towns'.

Create.cshtml

<div class="form-group">
@Html.LabelFor(model => model.FestivalTown, new { @class = "control-label col-md-2" })      
<div class="col-md-10">
@Html.DropDownList("towns", (IEnumerable<SelectListItem>)ViewData["Town"], new{@class = "form-control", @style="width:250px" })
@Html.ValidationMessageFor(model => model.FestivalTown)
</div>
@*@Html.Partial("ddlFestivalCounty");*@
</div>

Controller.cshtml

//Get
List<SelectListItem> Towns = new List<SelectListItem>();
Towns.Add(new SelectListItem { Text = "Please select your Town", Value = "SelectTown" });
var towns = (from t in db.Towns select t).ToArray();
for (int i = 0; i < towns.Length; i++)
{
Towns.Add(new SelectListItem
{
Text = towns[i].Name,
Value = towns[i].Name.ToString(),
Selected = (towns[i].ID == 0)
});
}

ViewData["Town"] = Towns;

//Post
festival.FestivalTown.Town = collection["Town"];

Model.cs

    public class Festival
{
    public int FestivalId { get; set; }

    [Required]
    [Display(Name = "Festival Name"), StringLength(100)]
    public string FestivalName { get; set; }

    [Required]
    [Display(Name = "Start Date"), DataType(DataType.Date)]
    public DateTime StartDate { get; set; }

    [Required]
    [Display(Name = "End Date"), DataType(DataType.Date)]
    public DateTime EndDate { get; set; }

    [Required]
    [Display(Name = "County")]
    public virtual County FestivalCounty { get; set; }

    [Display(Name = "Festival Location")]
    public DbGeography Location { get; set; }

    [Required]
    [Display(Name = "Town")]
    public virtual Town FestivalTown { get; set; }

    [Required]
    [Display(Name = "Festival Type")]
    public virtual FestivalType FType { get; set; }

    public UserProfile UserId { get; set; }
}

    public class Town
{
    public int ID { get; set; }
    [Display(Name = "Town")]
    public string Name { get; set; }
}
Was it helpful?

Solution

I suspect that this error occurs when you submit the form to the [HttpPost] action and not when you are rendering the form, right? And this action renders the same view containing the dropdown, right? And inside this [HttpPost] action you forgot to populate the ViewData["Town"] value the same way you did in your HttpGet action, right?

So, go ahead and populate this property the same way you did in your GET action. When you submit the form to your [HttpPost] action, only the selected value is sent to the controller. So you need to repopulate the collection values if you intend to redisplay the same view, because this view renders a dropdown which is attempting to bind its values from ViewData["Town"].

And here's what I mean in terms of code:

[HttpPost]
public ActionResult SomeAction(Festival model)
{
    ... bla bla bla

    // don't forget to repopulate the ViewData["Town"] value the same way you did in your GET action
    // if you intend to redisplay the same view, otherwise the dropdown has no way of getting
    // its values
    ViewData["Town"] = ... same stuff as in your GET action

    return View(model);
}

And all this being said, I would more than strongly recommend you using view models instead of this ViewData/ViewBag weakly typed stuff. Not only that your code will become much more clean, but even the error messages will start making sense.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top