Reputation: 2385
I ran across an issue where I was expecting Html.HiddenFor to resolve the id from my model and discovered that ModelStateCollection is constructed from the query parameters, post data, as well as your model (as discussed here https://stackoverflow.com/a/8749419/910348).
But what I do not understand is why does Html.DisplayFor resolve differently than HiddenFor. Here is my code:
// Model
public class FooModel
{
public int id { get; set; }
}
// Controller
public ActionResult Foo(int id)
{
var model = new FooModel { id = 111 };
return View(model);
}
// Form
@model MVCProject.Models.FooModel
@using (Html.BeginForm())
{
<fieldset>
<legend>FooModel</legend>
@Html.HiddenFor(model => model.id)
<p>ID: @Html.DisplayFor(model => model.id)</p>
<p><input type="submit" value="Save" /></p>
</fieldset>
}
The resulting HTML for a request /Home/Foo/999:
<input data-val="true" data-val-number="The field id must be a number."
data-val-required="The id field is required." id="id" name="id"
type="hidden" value="999" />
<p>ID: 111</p>
Is this expected behavior that HiddenFor and DisplayFor resolve their lambda expressions to different values? Why?
Upvotes: 2
Views: 738
Reputation: 25541
The reason why there is different behavior is because HiddenFor
is pulling from the ModelStateCollection
. It's an input and as a result that's where the framework is looking first.
DisplayFor
isn't attempting to render any sort of input, select, textarea, etc. It's just spitting out the value. Because it isn't an input of any type, it doesn't care about the ModelStateCollection
.
If you think about the flow of a normal web application, you are presented with a form that needs to be populated. Once you're done you submit the form and you are either taken to an entirely new page (with a fresh state) or you are returned to your current page to make changes or review the data. In most cases it makes sense to display the data that the user just submitted in their request.
Upvotes: 2