I have a ViewModel class containing a Dictionary (and other irrelevant things for this question):
public class MyViewModel {
public Dictionary<int, string> Data { get; set; }
/* ... */
}
Then I have a couple of GET
/POST
actions that deal with the dictionary. The GET
action will first fill the Dictionary<int, string>
with some data from the database, and then return a View
:
- the
.Key
s will be on hidden fields; and - the
.Value
s will be on a textareas for the user to edit.
The user will then submit this form, calling the POST
action. It will try to process the input (the process is irrelevant). Some of the Key
/Value
pairs will be valid, some will be invalid.
If there are invalid pairs, the POST
action will then reconstruct a ViewModel, but this time the dictionary should contain only the invalid pairs, and will redisplay the same View for the user to fix and try submitting again.
Question: what is the easiest & cleanest way to achieve this?
What I have so far (working fine), in the controller:
public ActionResult MyAction(MyViewModel vm) {
/* Process data */
if (are there invalid pairs?) {
var vmErrors = new MyViewModel();
/* ... fill the ViewModel ... */
vmErrors.Data =
vm.Data
.Where(x => IsInvalid(x))
.ToDictionary(x => x.Key, x => x.Value);
return View(vmErrors);
}
}
And the view:
<% var i = 0; foreach (var p in Model.Data) { %>
<%= Html.Hidden("vm.Data[" + i + "].key", vm.Key %>
<%= Html.TextArea("vm.Data[" + i + "].value", vm.Value %>
<% i++; } %>
The problem is that to please the model binder I must name my fields on the view with sequential ids. But I must also iterate over the Dictionary to extract the key/value pairs, so it cannot be a for (var i = 0; i < Model.Data.Count; i++) {...}
loop.