Replace the foreach loop in your view with a call to an editor template.
Up vote 1 down vote favorite share g+ share fb share tw.
I have the following controller and view. It is listing the values correctly using GET. When I click on the button it causes a POST.
However the value received in the controller is NULL. How do we correct it? HIGHLIGHTED CODE HttpPost public ActionResult CastVote(IEnumerable theProgramList) GET Image CODE public enum RatingEnum { Poor = 0, Neutral, Good, Excellent }; public class Program { public int ProgramID { get; set; } public string ProgramName { get; set; } public RatingEnum RatingID { get; set; } public string ProgramCategory { get; set; } } CONTROLLER namespace MyProgramRatingApp.
Controllers { public class ProgramController : Controller { List programList = new List() { new Program { ProgramID = 1,ProgramName = "Program1", ProgramCategory = "A" }, new Program { ProgramID = 2,ProgramName = "Program2", ProgramCategory = "B" }, new Program { ProgramID = 3,ProgramName = "Program3", ProgramCategory = "A" } }; // GET: /Program/ public ActionResult CastVote() { ViewBag. RatingEnum = GetRstingSelectList(); return View(programList); } // POST: /StoreManager/Create HttpPost public ActionResult CastVote(IEnumerable theProgramList) { if (ModelState. IsValid) { //Save the book in DB first and then redirectToAction.
Return RedirectToAction("CastVote"); } return View(theProgramList); } public static SelectList GetRstingSelectList() { Array values = Enum. GetValues(typeof(RatingEnum)); List items = new List(values. Length); foreach (var I in values) { items.
Add(new System.Web.UI.WebControls. ListItem { Text = Enum. GetName(typeof(RatingEnum), i), Value = ((int)i).ToString() } ); } return new SelectList(items); } } } VIEW @model IEnumerable @{ ViewBag.
Title = "CastVote"; } CastVote @using (Html.BeginForm()) { ProgramName RatingID ProgramCategory @foreach (var item in Model) { @Html. DisplayFor(modelItem => item. ProgramName) @Html.
DisplayFor(modelItem => item. RatingID) @Html. DisplayFor(modelItem => item.
ProgramCategory) @Html. DropDownListFor(model => item. RatingID, (SelectList)ViewBag.
RatingEnum, String. Empty) } } READING: dropdownlist set selected value in MVC3 Razor ASP. NET MVC 3 - Partial vs Display Template vs Editor Template IEnumerable property with MVC3 EditorTemplate ASP.
NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries Model Binding To A List asp.net .net asp.net-mvc asp.net-mvc-3 mvc link|improve this question edited Feb 21 at 5:37 asked Feb 20 at 6:26Lijo68318 73% accept rate.
DisplayFor is probably generating ProgramName (in the name attr) for the complete list which cannot be bound back to the model. Check the names in the html I think they need to be ProgramName0, ProgramName1 etc.. – Lavinski Feb 20 at 6:30 Since I am a newbie in MVC, I didn't quite understand your point. Could you please provide a code demo?
Also, I the number of programs is dynamic (from database) in real scenario. – Lijo Feb 20 at 6:33 1 to check what values are actually being posted accept a FormCollection parameter in your post action. – nathan gonzalez Feb 20 at 6:37 When I used FormCollection, there is only one string in allKeys.
It is "item. RatingID" – Lijo Feb 20 at 6:40.
Replace the foreach loop in your view with a call to an editor template: @model IEnumerable @{ ViewBag. Title = "CastVote"; } CastVote @using (Html.BeginForm()) { ProgramName RatingID ProgramCategory @Html.EditorForModel() } and then define the editor template which will be automatically rendered for each element in the model (~/Views/Shared/EditorTemplates/Program. Cshtml): @model MyProgramRatingApp.
Program @Html. EditorFor(x => x. ProgramName) @Html.
EditorFor(x => x. RatingID) @Html. EditorFor(x => x.
ProgramCategory) @Html. DropDownListFor( x => x. RatingID, (SelectList)ViewBag.
RatingEnum, String. Empty ) Notice that I have used @Html. EditorFor in the editor template instead of @Html.
DisplayFor in order to generate input fields. If you don't do that you won't get any values back in the controller because your form doesn't contain any input elements. If you don't want to show input fields you could use hidden inputs: @model MyProgramRatingApp.
Program @Html. DisplayFor(x => x. ProgramName) @Html.
HiddenFor(x => x. ProgramName) @Html. DisplayFor(x => x.
RatingID) @Html. HiddenFor(x => x. RatingID) @Html.
DisplayFor(x => x. ProgramCategory) @Html. HiddenFor(x => x.
ProgramCategory) @Html. DropDownListFor( x => x. RatingID, (SelectList)ViewBag.
RatingEnum, String. Empty ) The editor template will generate correct names for the input fields so that the model binder correctly binds the values. You may also take a look at the following article to better understand the wire format that is expected for collections.
Lijo, that's most probably because you made some mistake in the naming of your editor template. Make sure that it is located in ~/Views/Shared/EditorTemplates/ and that it is called Program.cshtml. If it is not showing it means that you didn't place the template at the correct place.
Double check once again. – Darin Dimitrov Feb 20 at 8:43 1 @Lijo, I made a mistake in my code. You should use @Html.
EditorFor instead of @Html. DisplayFor in the template. I have updated my answer to fix that.
A DisplayFor simply generates a label. You need to use an input field if you want to preserve the value when posting to the controller. – Darin Dimitrov Feb 20 at 8:55 @Lijo, you have 2 inputs for it.
One @Html. EditorFor(x => x. RatingID) and one @Html.DropDownListFor.
You must decide which one of the two to use in order to bind this value. Then remove the other. – Darin Dimitrov Feb 20 at 9:03 1 @Lijo, you seem to be using an enum type to bind the dropdown list to: ViewBag.RatingEnum.
This obviously cannot work with your x => x. RatingID because your RatingID property is an integer. Maybe you could try declaring it as a public RatingEnum ProgramID { get; set; } – Darin Dimitrov Feb 20 at 11:06 1 @Lijo, bu using a Html.
DisplayFor(x => x. ProgramName) and by placing an additional hidden field in order to pass the value Html. HiddenFor(x => x.
ProgramName). I have already explained this in my answer and even shown an example. – Darin Dimitrov Feb 207 at 6:51.
Thanks to Darin. I have accepted his answer. The complete solution is posted for the benefit of others reading this.
Note: EditorTemplate helped to avoid foreach loop and helped in proper object binding. Note: The EditorTemplate should be placed in proper folder and the filename should be based on convention. //Model namespace MyProgramRatingApp { public enum RatingEnum { Poor = 0, Neutral, Good, Excellent }; public class Program { public int ProgramID { get; set; } public string ProgramName { get; set; } public RatingEnum Rating { get; set; } public string ProgramCategory { get; set; } } } //Controller using System; using System.Collections.
Generic; using System.Web. Mvc; namespace MyProgramRatingApp. Controllers { public class ProgramController : Controller { List programList = new List() { new Program { ProgramID = 1,ProgramName = "Program1", ProgramCategory = "A" }, new Program { ProgramID = 2,ProgramName = "Program2", ProgramCategory = "B" }, new Program { ProgramID = 3,ProgramName = "Program3", ProgramCategory = "A" } }; // GET: /Program/ public ActionResult CastVote() { ViewBag.
RatingEnum = GetRstingSelectList(); return View(programList); } // POST: /StoreManager/Create HttpPost public ActionResult CastVote(IEnumerable theProgramList) { if (ModelState. IsValid) { //Save the book in DB first and then redirectToAction. Return RedirectToAction("CastVote"); } return View(theProgramList); } public static SelectList GetRstingSelectList() { Array values = Enum.
GetValues(typeof(RatingEnum)); List items = new List(values. Length); foreach (var I in values) { items. Add(new System.Web.UI.WebControls.
ListItem { Text = Enum. GetName(typeof(RatingEnum), i), Value = ((int)i).ToString() } ); } return new SelectList(items); } } } View(CastVote. Cshtml) @model IEnumerable @{ ViewBag.
Title = "CastVote"; } CastVote @using (Html.BeginForm()) { ProgramName ProgramCategory @Html.EditorForModel() } EditorTemplate(Program. Cshtml) @model MyProgramRatingApp. Program @Html.
DisplayFor(x => x. ProgramName) @Html. HiddenFor(x => x.
ProgramName) @Html. EditorFor(x => x. ProgramCategory) @Html.
DropDownListFor(x => x. Rating, (SelectList)ViewBag. RatingEnum, String.
Empty) @Html. HiddenFor(x => x. ProgramID).
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.