When I send the model back to the Controller, the model instance returns with all properties null.
public class ManageUserRolesViewModel
{
public PSUser PSUser { get; set; }
public SelectList Roles { get; set; }
public string SelectedRole { get; set; }
}
<table id="style-3" class="table style-3 table-hover" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Current Role</th>
<th>New Role</th>
<th>Manage Role</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.PSUser.FullName</td>
<td>@(await RolesService.GetUserMainRoleAsync(item.PSUser))</td>
<td>
<form asp-action="ManageUserRoles" asp-controller="UserRoles" method="post">
<input type="hidden" asp-for="@item.PSUser" />
<div class="flex flex-wrap gap-2 items-center">
<select asp-for="@item.SelectedRole" asp-items="@item.Roles" ></select>
</div>
<input type="submit" class="btn btn-primary" value="Assign Role">
</form>
</td>
<td>
</td>
</tr>
}
</tbody>
</table>
public async Task<IActionResult> ManageUserRoles(ManageUserRolesViewModel model)
{
//do stuff with model
}
I have tried putting the form tag before and after the tag, also changed the SelectList structure, changed the ViewModel instance name, Deleted the View code and created it all over again, and read countless of Stack Overflow posts about ViewModel bindings.
What am I doing wrong here? Any help will be greatly appreciated!
The name attribute of the select would be rendered as item.SelectedRole:
You could modify
public async Task<IActionResult> ManageUserRoles(ManageUserRolesViewModel model)
{
//do stuff with model
}
to
public async Task<IActionResult> ManageUserRoles(ManageUserRolesViewModel item)
{
//do stuff with model
}
Also every property of PUser that you want to receive in post method has to be rendered,modify
<input type="hidden" asp-for="@item.PSUser" />
to
<input type="hidden" asp-for="@item.PSUser.Id" />
<input type="hidden" asp-for="@item.PSUser.Name" />
......
Now it works on myside:
You could check this document for more details