Search code examples
c#asp.net-mvcasp.net-coremodel-bindingasp.net-mvc-viewmodel

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


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!


Solution

  • 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