I'd suggest you alter your view-model to match the requirements of your view. You can then use server-side code to map the posted view-model to the required model data.
For example:
public class ScoresViewModel
{
public List<CapabilityScoreViewModel> Scores { get; set; }
}
public class CapabilityScoreViewModel
{
public int Id { get; set; }
public string CapabilityName { get; set; }
[Required, Range(1, 5)]
public byte? Score { get; set; }
}
@model CapabilityTracker.ViewModels.ScoresViewModel
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<table class="table">
<thead>
<tr>
<th scope="col">
Capability Name
</th>
<th scope="col">
Score
</th>
</tr>
</thead>
<tbody>
@for (int index = 0; index < Model.Scores.Count; index++)
{
<tr>
<th scope="row">
@Html.HiddenFor(m => m.Scores[index].Id)
@Html.HiddenFor(m => m.Scores[index].CapabilityName)
@Html.DisplayFor(m => m.Scores[index].Id)
@Html.DisplayFor(m => m.Scores[index].CapabilityName)
</th>
<td>
@Html.EditorFor(m => m.Scores[index].Score)
</td>
</tr>
}
</tbody>
</table>
<p>
<button type="submit">
Create
</button>
</p>
}
[HttpGet]
public ActionResult CreateScores()
{
List<CapabilitiesModel> capabilities = ...;
ScoresViewModel model = new ScoresViewModel
{
Scores = capabilities
.Select(c => new CapabilityScoreViewModel
{
Id = c.Id,
CapabilityName = c.CapabilityName,
})
.ToList(),
};
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateScores(ScoresViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
List<ScoreModel> scores = model.Scores
.Select(s => new ScoreModel
{
Capability = s.Id,
Score = s.Score.GetValueOrDefault(),
})
.ToList();
...
}