In my application I have a drop down list to represent different choices. Note that Paragraph is a model and the section is just one field in the model.
@Html.DropDownList("Sections")
And here is my controller.
public ActionResult Edit(int id)
{
var paragraph = db.Paragraphs.Find(id);
ViewBag.Sections = new SelectList(
db.Sections.Select(s => new { s.ID, s.Name }),
"ID", "Name", paragraph.SectionID
);
return View(paragraph);
}
[HttpPost]
public ActionResult Edit(Paragraph paragraph, HttpPostedFileBase document)
{
if (ModelState.IsValid)
{
// Do some stuff.
}
ViewBag.Sections = new SelectList(
db.Sections.Select(s => new { s.ID, s.Name }),
"ID", "Name", paragraph.SectionID
);
return View(paragraph);
}
When I submit the form though the drop down list is not bound to the model. Causing ModelState.IsValid to be false and making my life horrible. Any suggestions?
EDIT: When I submit the form I get the following error:
There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'Sections'.
EDIT: It appears that I only get the preceding error when I try to submit the file.
EDIT: Model
public class Paragraph
{
public int ID { get; set; }
[Required]
public int Major { get; set; }
[Required]
public int Minor { get; set; }
[Required(ErrorMessage = "Name is required")]
[StringLength(4000)]
public string Name { get; set; }
public int SectionID { get; set; }
public virtual Section Section { get; set; }
}
Form: (It’s a lot.)
<form class="form-horizontal" action="/Paragraph/Edit" method="post" enctype="multipart/form-data">
<fieldset>
<div class="control-group">
<label class="control-label" for="section">Section</label>
<div class="controls">
@Html.DropDownList("Sections")
</div>
</div>
<div class="control-group">
<label class="control-label" for="major">Major</label>
<div class="controls">
<input type="number" class="input-large" name="major" value="@Model.Major" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="minor">Minor</label>
<div class="controls">
<input type="number" class="input-large" name="minor" value="@Model.Minor" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="name">Name</label>
<div class="controls">
<input type="text" class="input-large" name="name" value="@Model.Name" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="document">Document</label>
<div class="controls">
<input type="file" class="input-file" name="document" />
</div>
</div>
<div class="form-actions">
<input type="submit" class="btn btn-primary" value="Save" />
<a class="btn" href="/Paragraph/Show/@Model.ID">Cancel</a>
</div>
</fieldset>
</form>
This is late, but better late than never. When you use one of the helpers provided by
HtmlHelperit generates theinputname behind the scenes. The generated format for this name isModel.Field. For example, a paragraph with a field called “Name” would becomeParagraph.Name.The definition for
DropDownListthat accepts one parameter uses the name of the drop-down list as the name of theinputthough. So, a call toDropDownList("Sections")would create aninputwith a name of “Sections.”In the end though, I decided to concede to Razor and use the built-in HTML helpers. So my drop-down list code looks like:
DropDownListFor(vm => vm.Paragraph.SectionID, Models.Sections).