Model binding for ViewModel in ASP.NET Core MVC not working

65 Views Asked by At

When I send the model back to the Controller, the model instance returns with all properties null.

  1. This is the ViewModel with some properties, including a SelectList and a model instance.
 public class ManageUserRolesViewModel
 {
     public PSUser PSUser { get; set; }

     public SelectList Roles { get; set; }

     public string SelectedRole { get; set; }
  
 }
  1. Then in the View I have a datagrid table inm which I added a form with a select tag so the user can choose an option per line and then submit the form
<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>
  1. And in my post method I try to catch the ViewModel object with its values:
 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!

1

There are 1 best solutions below

0
Ruikai Feng On BEST ANSWER

The name attribute of the select would be rendered as item.SelectedRole:

enter image description here

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:

enter image description here

You could check this document for more details