I am facing a problem most of you (including me) would solve immeditately by placing a hidden input to forms, but this time I have tried almost everything. I would like to modify an InputForm entity by adding a SolarPanelType entity. Because of the loads of another options, I use viewmodels embedded as you can see
public class InputFormViewModel
{
public InputForm InputForm { get; set; }
public IEnumerable<TetoTipus> TetoTipusEnumerable { get; set; }
public IEnumerable<TetoFedes> TetoFedesEnumerable { get; set; }
public IEnumerable<TetoDoles> TetoDolesEnumerable { get; set; }
public IEnumerable<NapelemElhelyezes> NapelemElhelyezesEnumerable { get; set; }
public IEnumerable<NapelemTipus> NapelemTipusEnumerable { get; set; }
}
public class ModifyInputFormViewModel
{
public InputFormViewModel InputFormViewModel;
public SelectList SolarPanelTypesList { get; set; }
}
And I initialize them in my controller like this
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
ModifyInputFormViewModel modifyInputFormViewModel = new()
{
InputFormViewModel = new InputFormViewModel
{
InputForm = await _inputFormService.FindInputFormAsync(id),
TetoTipusEnumerable = await _inputFormService.GetTetoTipusokAsync(),
TetoFedesEnumerable = await _inputFormService.GetTetoFedesekAsync(),
TetoDolesEnumerable = await _inputFormService.GetTetoDolesekAsync(),
NapelemElhelyezesEnumerable = await _inputFormService.GetNapelemElhelyezesekAsync(),
NapelemTipusEnumerable = await _inputFormService.GetNapelemTipusokAsync()
},
SolarPanelTypesList = new SelectList(await _solarPanelTypeService.GetSolarPanelTypesAsync(), "ID", "DisplayString")
};
if (modifyInputFormViewModel.InputFormViewModel.InputForm == null)
{
return NotFound();
}
return View(modifyInputFormViewModel);
}
And the POST method
[HttpPost, ValidateAntiForgeryToken, Authorize]
public async Task<IActionResult> Edit(int id, ModifyInputFormViewModel modifyInputFormViewModel)
{
if (id != modifyInputFormViewModel.InputFormViewModel.InputForm.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
await _inputFormService.ModifyInputFormAsync(modifyInputFormViewModel.InputFormViewModel.InputForm);
return RedirectToAction(nameof(Index));
}
return View(modifyInputFormViewModel);
}
Finally, here is the crucial part of Edit view
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="InputFormViewModel.InputForm.ID" />
<div class="form-group">
<label asp-for="InputFormViewModel.InputForm.SolarPanelType" class="control-label"></label>
<select asp-for="InputFormViewModel.InputForm.SolarPanelTypeID" asp-items="@Model.SolarPanelTypesList" class="form-control"></select>
</div>
<div class="form-group">
<label asp-for="InputFormViewModel.InputForm.MonthlyElectricityBill" class="control-label"></label>
<input asp-for="InputFormViewModel.InputForm.MonthlyElectricityBill" class="form-control" />
<span asp-validation-for="InputFormViewModel.InputForm.MonthlyElectricityBill" class="text-danger"></span>
</div>
<section id="TetoTipusSection">
<h5>@Html.DisplayNameFor(model => model.InputFormViewModel.InputForm.TetoTipus)</h5>
<p>
@foreach (TetoTipus tetoTipus in Model.InputFormViewModel.TetoTipusEnumerable)
{
<label>
<input type="radio" asp-for="InputFormViewModel.InputForm.TetoTipusID" value="@tetoTipus.ID" /> @tetoTipus.Name
</label>
<br />
}
</p>
<hr />
</section>
[...]
</form>
Last important information is that the view renders EXACTLY what I want, the hidden input contains InputForm.ID correctly, but then the post method receives NULL value.
2
Answers
Update you code like below:-
and your controller:-
Hope it will resolve your issue.
fix the view, since you use AntiForgeryToken add it to form
and action input parameter should be the same as a model, remove id