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?
HTML helpers are built with model binding conventions in mind. So for example I suppose that you have the following model:
and the corresponding view is strongly typed to
MyViewModel
.So when you use:
the helper generates:
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:
I guess that your problems are coming from the fact that your controller action is taking an
ItemViewModel
as parameter instead ofMyViewModel
:So you could use the
[Bind]
attribute and specify a prefix to help the model binder: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.