.NET Core 3.1 with EF Core, trying to update data loaded into a form, but for some reason it sets the Id = 0 on submit, and I have no idea why. Or, if I explicitly set the id value, the controller gets a null value for all the records. Importantly, it's a list of entities that I'm sending down to the db.
I can create multiple records just fine using the same form. But if I load the form with existing records, and want to make changes, I can't. The Id of each record gets set to zero, if I don't put the Id in for each record. If I do put the Id of each record, the form seems to submit correctly, as I'm looking at Chrome DevTools and see that the values are there, including the Id, but then the controller gets that data, and it's null...
ETA It looks like the 41st row is causing the issue when I do submit the form with the Id included for each row. What I don't know is if that means 41 rows is too many, or there is some issue with the data itself, which means the controller won't pick up any of it...but neither of these make sense, since the form loads the 62 rows just fine.
Here's a simplified version of it, with key pieces included so it makes sense.
My model:
@model List<EvaluationsModel>
My form:
@{
var createOrUpdate = "Update";
if (Model[0].IsCreate)
{
createOrUpdate = "Create";
}
}
<form id="evalForm" asp-action="@createOrUpdate">
@for (var i = 0; i < Model.Count; i++)
{
<textarea asp-for="@Model[i].Comments" rows="5" cols="75"></textarea>
<input asp-for="@Model[i].Id" type="hidden" />
}
<input type="submit" id="submitButton" value="@createOrUpdate" class="btn btn-primary" />
My controller method:
public IActionResult Update(List<EvaluationsModel> evalRows)
{
_dostuffWith(evalRows);
return Redirect(toGet);
}
The original problem is that there were checkbox entries that were being doubled, and adding the Id value broke the submission of the form. I hadn't included the checkbox in the original code I submitted because I didn't think that was connected to the issue.
After lots of searching, this is the (final) answer I've come up with:
Upgrade to dotnet core 5.0 or greater.
In Configure Services
in Startup.cs
, add this line:
services.Configure(options => options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode = CheckBoxHiddenInputRenderMode.None);
The CheckBoxHiddenInputRenderMode
has three options; "none" will prevent the 2nd set of checkboxes from materializing. The other two options will determine where the 2nd set gets generated: either at the end of the form (default), or inline.
I haven't found any documentation showing how to implement this behavior as of this writing.
The problem was twofold:
<input asp-for="@Model[i].IsCorrect" />
item, I get two entries. (The reason MVC does this is to make sure that something gets submitted, because the HTML5 spec says that if a checkbox isn't checked, don't submit anything at all. MVC make sure that something instead of nothing gets submitted.)I saw this, but it didn't look strange to me because of some other things I had going on. So the form was sending all the regular entries, plus two of the bool values (instead of just one, like all the others). Adding the id meant I was sending more than the model was expecting.
But problem solved.
References: the commit for the new options.