Reputation:
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>
Upvotes: 1
Views: 6446
Reputation: 1581
Friend had the same problem when doing cascading dropdownlist
And there is no why to bind parent dropdownlist. So what I did was to fill the parent dropdownlist the same way as the soon. Created an action, called it on json and filled it using jquery.
My action on controller:
public ActionResult GetStates()
{
if (Request.IsAjaxRequest())
{
using (MyModel banco = new myModel())
{
return Json(new SelectList(banco.SyStates.ToList(), "StateId", "StateName"), JsonRequestBehavior.AllowGet);
}
}
return View();
}
The view:
<select id="StateList" name="StateList"></select>
<script>
$(document).ready(function () {
var URL = "/ControllerName/GetStates";
$.getJSON(URL, function (data) {
var items = '<option>Selecione o estado</option>';
$.each(data, function (i, State) {
items += "<option value='" + State.Value + "'>" + State.Text + "</option>";
// state.Value cannot contain ' character. We are OK because state.Value = cnt++;
});
$('#StateList').html(items);
//$('#CitiesTrID').show();
})
});
Got cascading example on: http://blogs.msdn.com/b/rickandy/archive/2012/01/09/cascasding-dropdownlist-in-asp-net-mvc.aspx
Upvotes: 0
Reputation: 2354
So weird! I used to use
@Html.DropDownList("permissionsID", String.Empty)
and it worked fine - all of a sudden, im receiving the same problem. The ddl is not submitting its selected value on the Create (posted) controller method)
So i used
@Html.DropDownListFor(model => model.permissionID, (IEnumerable<SelectListItem>)ViewBag.permissionsID)
and it worked fine!
However I have older controllers that still work till today using the old method - just its not liking it for my new controllers!
It really defies logic...
Upvotes: 0
Reputation:
This is late, but better late than never. When you use one of the helpers provided by HtmlHelper
it generates the input
name behind the scenes. The generated format for this name is Model.Field
. For example, a paragraph with a field called "Name" would become Paragraph.Name
.
The definition for DropDownList
that accepts one parameter uses the name of the drop-down list as the name of the input
though. So, a call to DropDownList("Sections")
would create an input
with 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)
.
Upvotes: 0
Reputation: 4915
Change your HTML code to:
@Html.DropDownListFor(m => m.SectionID, ViewBag.Sections as SelectList)
If you don't have a model for this page, then use the code below:
@Html.DropDownList("Sections", ViewBag.Sections as SelectList)
Upvotes: 1
Reputation: 12263
Just wondering why you are not using strongly type helpers like Html.TextBoxFor etc? You can pass optional html attributes with them if required
I'd make your dropdownlist
@Html.DropDownListFor(model =>model.SectionID,(IEnumerable<SelectListItem>) ViewBag.Sections)
Others
@Html.HiddenFor(model =>model.ID)
@Html.TextBoxFor(model =>model.Name)
@Html.TextBoxFor(model =>model.Major)
@Html.TextBoxFor(model =>model.Minor)
File can be <input type="file" class="input-file" name="document" />
That should give you the model to bind to. You will be sure of getting the correct names etc back. Also I am including the ID as part of the form.
Upvotes: 1