Why does Html Helper add prefix to attributes for child item of view model?
razor
Solution
HTML helpers are built with model binding conventions in mind. So for example I suppose that you have the following model:
public class MyViewModel
{
public ItemViewModel Item { get; set; }
// ... other properties
}
public class ItemViewModel
{
public int ItemID { get; set; }
}
and the corresponding view is strongly typed to `MyViewModel`.
So when you use:
@Html.HiddenFor(model => model.Item.ItemID)
the helper generates:
<input id="Item_ItemID" name="Item.ItemID" type="hidden" value="234" />
because that's what would allow you to properly bind your view model in the corresponding controller action when the form is POSTed back to the server:
[HttpPost]
public ActionResult Process(MyViewModel model)
{
// model.Item.ItemID will be correctly bound here from the hidden field value
}
I guess that your problems are coming from the fact that your controller action is taking an `ItemViewModel` as parameter instead of `MyViewModel`:
[HttpPost]
public ActionResult Process(ItemViewModel model)
{
// model.ItemID will not be correctly bound here from the hidden field value
}
So you could use the `[Bind]` attribute and specify a prefix to help the model binder:
[HttpPost]
public ActionResult Process([Bind(Prefix="Item")] ItemViewModel model)
{
// model.ItemID will be correctly bound here from the hidden field value
}
or simply design another view model stripping all the unnecessary properties from it and leaving only the `Item` property. Now your controller action could take this specifically designed view model.
So as you can see at the end of the day you could perfectly fine control the model binding if you design your view models correctly. It's all about view models in ASP.NET MVC. They solve all problems.
Problem
I have a view model with a single child entity and various other properties. In my view I want to display a form for the child entity. Using the following code: ``` @Html.HiddenFor(model => model.Item.ItemID) ``` produces the following output: ``` <input id="Item_ItemID" name="Item.ItemID" type="hidden" value="234" /> ``` As you can see, the Html helper has prefixed the `id` and `name` attributes, whereas I would have expected the output to be ``` <input id="ItemID" name="ItemID" type="hidden" value="234" /> ``` Consequently, the former output causes an error when the form is submitted because the form elements do not correspond to properties on the child entity. I know I can get around this by hard-coding the hidden field ``` <input id="ItemID" name="ItemID" type="hidden" value="@Model.Item.ItemID" /> ``` which kind of defeats the reason for having Html helpers, or creating a partial view and passing in the child object ``` @{Html.RenderPartial("ItemForm", Model.Item);} ``` I am aware of being able to pass in html attributes to the method, and also writing my own extension method, but things get more complicated when data validation and jQuery are involved i.e the following code: ``` @Html.EditorFor(model => model.Item.Title) @Html.ValidationMessageFor(model => model.Item.Title) ``` produces this code: ``` <input class="text-box single-line" data-val="true" data-val-required="The Title field is required." id="Item_Title" name="Item.Title" type="text" value="Some text" /> <span class="field-validation-valid" data-valmsg-for="Item.Title" data-valmsg-replace="true"></span> ``` so there needs to be an elegant method to keep the property names in synch. So can anyone answer why does an HtmlHelper add a prefix to attributes for a child item of a view model? And as a follow up question, is there any other neat way of preventing the prefix from being added?