I am trying to display a form for merging two contacts in ASP.net MVC 5. The form should look like this where each row holds a radio button group consisting of 2 options:
The form shows up just fine, and the radio groups work (I can select each group). However, when the model is posted back to the server, the Values
list is empty (not preserved). I would like to get both the selected id but of course also the actual text value back in the controller. I prefer to do this using Editor Templates and if possible without for
loops.
The current results (Values = null):
EDIT to respond to comments: I would prefer not to re-fetch the values in the controller again, because it results in a call to a web service. I have tried some variants of HiddenFor
without results.
My models look like this:
public class Contact
{
public List<ContactRow> Rows { get; set; }
public Contact()
{
this.Rows = new List<ContactRow>();
this.Rows.Add(new ContactRow("First Name", "Homer", "Homie"));
this.Rows.Add(new ContactRow("Last Name", "Simpson", "Simson"));
this.Rows.Add(new ContactRow("Email", "mail1", "mail2"));
this.Rows.Add(new ContactRow("Company Phone", "Phone1", "Phone2"));
this.Rows.Add(new ContactRow("Mobile Phone", "Mobile1", "Mobile2"));
}
}
public class ContactRow
{
public int Selection { get; set; }
public string Label { get; set; }
public List<ValueSet> Values { get; set; }
public ContactRow(string Label, string LeftValue, string RightValue, int Selection = 0)
{
if (LeftValue== null) LeftValue= "";
if (RightValue== null) RightValue= "";
this.Label = Label;
this.Selection = Selection;
this.Values = new List<ValueSet>(2);
this.Values.Add(new ValueSet() { ID = 0, ValueText = LeftValue});
this.Values.Add(new ValueSet() { ID = 1, ValueText = RightValue});
}
public ContactRow() { }
}
public class ValueSet
{
public int ID { set; get; }
public string ValueText { set; get; }
}
The Controller:
public ActionResult Index()
{
Contact model = new Contact();
return View(model);
}
public ActionResult MergeContacts(Contact model)
{
return RedirectToAction("Index");
}
And the views:
Index.cshtml
@model RadioTest.Models.Contact
@{
ViewBag.Title = "Home Page";
}
@using (Html.BeginForm("MergeContacts", "Home", FormMethod.Post, new { encType = "multipart/form-data", id = "contactDetailsForm", name = "contactDetailsForm" }))
{
<div>
<table class="table" width="100%">
<tr>
<th style="text-align:left">Label</th>
@*<th style="text-align:right">R1</th>*@
<th style="text-align:left">
Left Value
</th>
@*<th style="text-align:right">R2</th>*@
<th style="text-align:left">
Right Value
</th>
</tr>
@Html.EditorFor(model => model.Rows)
</table>
<input type="submit" />
</div>
}
Editor Template for ContactRow:
ContactRow.cshtml
@model RadioTest.Models.ContactRow
<tr>
<td style="text-align:left">
@Html.DisplayFor(model => model.Label)
</td>
@foreach (var v in Model.Values)
{
<td style="text-align:left">
@Html.RadioButtonFor(model => model.Selection, v.ID) @v.ValueText
</td>
}
</tr>
@Html.HiddenFor(model => model.Label)
Just change your foreach to for:
@model MVCApp.Controllers.ContactRow
<tr>
<td style="text-align:left">
@Html.DisplayFor(model => model.Label)
</td>
@for (int i = 0; i < Model.Values.Count; i++)
{
<td style="text-align:left">
@Html.RadioButtonFor(model => model.Selection, Model.Values[i].ID) @Model.Values[i].ValueText
@Html.HiddenFor(model => Model.Values[i].ID)
@Html.HiddenFor(model => Model.Values[i].ValueText)
</td>
}
</tr>
@Html.HiddenFor(model => model.Label)