I'm working on an asp-MVC application and facing the following issue: Here is a working code:
<div id="detailsTemplates">
@for (var i = 0; i < Model.Filter.itemDetails.Count; i++)
{
<table>
<tr>
<td>
@Html.TextBoxFor(model => model.Filter.itemDetails[i].iD)
</td>
</tr>
</table>
}
Now in the post action in my controller I get the inserted value correctly.
Now, when I change the code to a partial view:
<div id="detailsTemplates">
@for (int i = 0; i < Model.Filter.itemDetails.Count; i++)
{
Html.RenderPartial("itemDetailsUserControl", Model.Filter.itemDetails[i]);
}
</div>
and the partial view looks like the following:
<div id="detailsTemplates">
<table>
<tr>
<td>
@Html.TextBoxFor(item => item.iD)
</td>
</tr>
</table>
}
Now the value is not transffered via the post.
What am I doing wrong?
The context of the model in the view is from the model being passed to it. E.g. by passing
Model.Filter.CustomsitemDetails[i]
to your partial, you have changed the root from the Model object to your CustomiseDetails object. (so the name of the input will be "CustomsItemClassificationID" instead of "Filter.CustomsitemDetails[i].CustomsItemClassificationID", and so will not be rebound when posted, as will no longer match the property it is being bound to.
The correct way to do this is to use an Editor Template. This will preserve the model's origin. To do this, Create a folder called EditorTemplates under Views > Shared.
Copy your partial into it, and rename it to be called the name of your type. For example, if the type of Model.Filter.CustomsitemDetails[i] is CustomsitemDetail then your file under the editor template folder will be called CustomsitemDetails.cshtml.
Now, instead of
@Html.RenderPartial("CustomsItemDetailsUserControl", Model.Filter.CustomsitemDetails[i]);
Use
@Html.EditorFor(m => m.Filter.CustomitemDetails[i])
Alternatively, if you don't want to rename or move your file, you can specify it's current location instead:
@Html.EditorFor(m => m.Filter.CustomitemDetails[i], "~/Views/{controller}/CustomsItemDetailsUserControl.cshtml")
UPDATE
So I've learnt something new:
If a template whose name matches the templateName parameter is found in the controller's EditorTemplates folder, that template is used to render the expression. If a template is not found in the controller's EditorTemplates folder, the Views\Shared\EditorTemplates folder is searched for a template that matches the name of the templateName parameter. If no template is found, the default template is used. from MSDN.
So contrary to the second part of my answer, you do need to move your partial to
"~/Areas/TaxCalculation/Views/Home/EditorTemplates/CustomsItemDetailsUserControl.cshtml"
And use:
@Html.EditorFor(m => m.Filter.CustomitemDetails[i], "CustomsItemDetailsUserControl")
UPDATE 2
As per Stephen's comment - EditorFor() has an overload that accepts IEnumerable so you can just use
@Html.EditorFor(m => m.Filter.CustomitemDetails, "CustomsItemDetailsUserControl")
Or if you have an EditorTemplate named CustomitemDetails.cshtml located in the /Views/Shared/EditorTemplates/ folder:
@Html.EditorFor(m => m.Filter.CustomitemDetails)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With