Tibebe
Tibebe

Reputation: 45

ViewModel Updated with Ajax, Model does not bind

I have organizations as clients. Under each organization there are several users. In the view, when an organization is selected from a dropdown list, users under that specific organization are updated from database using Ajax. When I post the model, the users list is null. I tried several options, but nothing seems to work. This is a simplified version of the final code I have.

public class AccessModel
{
    public List<Organization> AllOrganizations { get; set; }
    public List<UserModel> Users { get; set; }
    //and several other properties 
}

My Get Action

[HttpGet]
public ActionResult GrantAccess()
         {
             var model = new AccessModel();
             model.AllOrganizations = db.Organizations.ToList(); 
             return View(model);   
         }

My View

@model MyModels.AccessModel
 @using (Html.BeginForm("GrantAccess", "Access", FormMethod.Post))
 {
 <div>
   @Html.DropDownList("Organizations", new SelectList(Model.AllOrganizations, "Id", "Name"),
       "choose", new { htmlAttributes = new { @onchange = "getUsers(this.value)" })
  </div>
<div id="Users">
   @{Html.RenderPartial("_UsersList", Model.Users);}
</div>
 }

My Jquery

<script>
    function getUsers(str) {
        $("#Users").load('@(Url.Action("ReturnUsers", "Product", null))?orgNumber=' + str);            
    }
</script>

My Action that renders the Partial page when called from Ajax

public ActionResult ReturnUsers(int orgNumber)
         {
             var usersList= db.Users.Where(u => u.OrganizationId == orgNumber).ToList();
             var model= new AccessModel();
             model.Users = usersList; 
             return PartialView("_UsersList", model); 
         }

The Partial page _UsersList.cshtml

@model AccessModel

@if (Model.Users != null)
{
    foreach (var item in Model.Users)
    {  
    <fieldset>
        @Html.HiddenFor(modelItem => item.User.Id)
        @Html.CheckBoxFor(modelItem => item.isSelected)
        @Html.DisplayFor(modelItem => item.User.LastName)
        @Html.DisplayFor(modelItem => item.User.FirstName)
    </fieldset>
    }
}

And finaly, The Post Action

[HttpPost]
public ActionResult GrantAccess(AccessModel model)
         {           
            //here model.Users is null!
         }

The view displays the users alright, only the values are not passed to my Post Model. Any suggestions?

Upvotes: 1

Views: 103

Answers (1)

hutchonoid
hutchonoid

Reputation: 33306

If you use a for loop instead of a foreach the name attribute is rendered in a format that the model binder can pickup.

@model AccessModel

@if (Model.Users != null)
{
    @for (var i = 0; i < Model.Users.Count; i++)
    {  
    <fieldset>
        @Html.HiddenFor(modelItem => Model.Users[i].Id)
        @Html.CheckBoxFor(modelItem => Model.Users[i].isSelected)
        @Html.DisplayFor(modelItem => Model.Users[i].LastName)
        @Html.DisplayFor(modelItem => Model.Users[i].FirstName)
    </fieldset>
    }
}

Upvotes: 2

Related Questions