In my view model, I have a list of objects. I iterate these objects, and create controls for each of them. In the situation below, I want to show people a textbox and a button for each object. When the user clicks the button, a post is made, and I can save the data in my controller.
In the UI, a user can change the form they want, and click save.
My problem is the model is null when it's posted to the controller..
My Razor code:
using (Html.BeginForm())
{
foreach (var contributor in Model.Contributor)
{
@Html.HiddenFor(model => contributor.Id)
<div class="formrow">
@Html.ValidationSummary(true)
</div>
<h2>@Html.TextRaw("AuthorInfo", "Author")</h2>
<div class="formrow">
@Html.EditorFor(model => contributor.FirstName)
<div class="formvalidation">
@Html.ValidationMessageFor(model => contributor.FirstName)
</div>
</div>
<div class="formrow right">
<input type="hidden" name="formsubmitted" value="true" />
<input type="submit" class="button" value="@Html.Text("ButtonText", "Save")" />
</div>
}
}
My view model code
public class ProfileModel
{
public string Message { get; set; }
public List<PublisherModel> Publisher { get; set; }
public List<ContributorModel> Contributor { get; set; }
public ContributorModel NewContributor { get; set; }
}
My controller code
[HttpPost]
public ActionResult Mine(ProfileModel model, string newuser)
{
//
}
How to fix it?
I guess I have to expand my view model with a way to store the changes in some way. But I really can't see how.
Right now all the properties in the ProfileModel is null when it reaches the controller.
Any ideas?
Basically the problem is that default model binder is unable to bind collection items correctly in foreach loop. In other words, it names the element incorrectly and that's why the collection displays as null in parameters.
I'm sure there are all kinds of different workarounds, helpers and stuff but I'm not familiar with those, so I just use for loop instead of foreach, this way the elements are named correctly.
Try this:
@for (int i = 0; i < Model.Contributor.Count(); i++)
{
@Html.HiddenFor(model => Model.Contributor[i].Id)
<div class="formrow">
@Html.ValidationSummary(true)
</div>
<h2>@Html.TextRaw("AuthorInfo", "Author")</h2>
<div class="formrow">
@Html.EditorFor(model => Model.Contributor[i].FirstName)
<div class="formvalidation">
@Html.ValidationMessageFor(model => Model.Contributor[i].FirstName)
</div>
</div>
<div class="formrow right">
<input type="hidden" name="formsubmitted" value="true" />
<input type="submit" class="button" value="@Html.Text("ButtonText", "Save")" />
</div>
}
I suggest you to use a debugging tool to see if elements have correct name attribute, in your case they should look like Contributor[0].Id, Contributor[0].FirstName etc.
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