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<Program> 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<Program> programList = new List<Program>()
{
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<Program> 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<System.Web.UI.WebControls.ListItem> items = new List<System.Web.UI.WebControls.ListItem>(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<MyProgramRatingApp.Program>
@{
ViewBag.Title = "CastVote";
}
<h2>CastVote</h2>
@using (Html.BeginForm())
{
<table>
<tr>
<th style="border:1px solid Teal; background-color:Gray">
ProgramName
</th>
<th style="border:1px solid Teal; background-color:Gray">
RatingID
</th>
<th style="border:1px solid Teal; background-color:Gray">
ProgramCategory
</th>
<th style="border:1px solid Teal; background-color:Gray"></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td style="border:1px solid Teal">
@Html.DisplayFor(modelItem => item.ProgramName)
</td>
<td style="border:1px solid Teal">
@Html.DisplayFor(modelItem => item.RatingID)
</td>
<td style="border:1px solid Teal">
@Html.DisplayFor(modelItem => item.ProgramCategory)
</td>
<td style="border:1px solid Teal">
@Html.DropDownListFor(model => item.RatingID, (SelectList)ViewBag.RatingEnum, String.Empty)
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Cast Vote" />
</p>
}
READING:
-
ASP.NET MVC 3 – Partial vs Display Template vs Editor Template
-
ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries
-
Model Binding To A List
Replace the
foreachloop in your view with a call to an editor template:and then define the editor template which will be automatically rendered for each element in the model (
~/Views/Shared/EditorTemplates/Program.cshtml):Notice that I have used
@Html.EditorForin the editor template instead of@Html.DisplayForin 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: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.