I have a peculiar problem – I have a ViewModel with a List in it used to display a list of images:
public List<int> TrackerKeys { get; set; }
This is used in two places in the page:
@for (int i = 0; i < Model.TrackerKeys.Count(); i++)
{
@Html.GenerateImage(PageModes.Http, Model.TrackerKeys[i])
}
And also
@for (int i = 0; i < Model.TrackerKeys.Count(); i++)
{
@Html.HiddenFor(model => model.TrackerKeys[i])
}
This is sat inside a form – when the form is submitted, if a validation error occurs, the TrackerKeys property is updated with a new random set of numbers. I am passing the previous list back to ensure the user does not see the same image again.
Tracker keys is correctly set and passed back to the View.
My problem is:
The images correctly display the new images based on the new values in the list
However
The values of the hidden fields are not updated to the new values – they retain the original values.
Any ideas? Is this a bug with MVC3? any input would be greatly appreciated. Thank you.
Edit
Html before submission:
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/26.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/33.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/8.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/30.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/6.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/18.gif" width="35" />
And
<input id="TrackerKeys_0_" name="TrackerKeys[0]" type="hidden" value="26" />
<input id="TrackerKeys_1_" name="TrackerKeys[1]" type="hidden" value="33" />
<input id="TrackerKeys_2_" name="TrackerKeys[2]" type="hidden" value="8" />
<input id="TrackerKeys_3_" name="TrackerKeys[3]" type="hidden" value="30" />
<input id="TrackerKeys_4_" name="TrackerKeys[4]" type="hidden" value="6" />
<input id="TrackerKeys_5_" name="TrackerKeys[5]" type="hidden" value="18" />
And after the post:
correct new values here…
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/16.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/20.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/11.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/19.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/26.gif" width="35" />
<img alt="Security Character" height="35" src="http://localhost:51414/content/imagescss/15.gif" width="35" />
and…
still retaining old values…
<input id="TrackerKeys_0_" name="TrackerKeys[0]" type="hidden" value="26" />
<input id="TrackerKeys_1_" name="TrackerKeys[1]" type="hidden" value="33" />
<input id="TrackerKeys_2_" name="TrackerKeys[2]" type="hidden" value="8" />
<input id="TrackerKeys_3_" name="TrackerKeys[3]" type="hidden" value="30" />
<input id="TrackerKeys_4_" name="TrackerKeys[4]" type="hidden" value="6" />
<input id="TrackerKeys_5_" name="TrackerKeys[5]" type="hidden" value="18" />
controller action
[HttpPost]
public ActionResult EmployerRegistration(EmployerViewModel Model)
{
if (ModelState.IsValid)
{
//do bits here
}
Model.TrackerKeys = Helper.GenerateNewNumbers(Model.TrackerKeys);
return View(Model);
}
Oh no, that’s by design and it is how all HTML helpers work in ASP.NET MVC. HTML helpers (such as
Html.TextBoxFor,Html.HiddenFor, …) first look at the ModelState when binding their values and after that they look at the Model. So if you intend to modify some property of your model inside the POST controller action and this property was part of the POST body, you will have to remove the old values from the ModelState first:or if you don’t want to clear the entire ModelState (as this will remove all values and any corresponding modelstate errors that might be associated to them) you could remove only those keys that you actually modify: