Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC CheckBoxList model binding with non boolean

I want to bind a List to CheckBox and get the selected values. I need to display two such Checkbox tables and have to retrieve both the IDs.

Below is my ViewModel

public partial class ViewModel_Role_Security
{
    public List<Roles> oRoleMaster { get; set; }
    public List<Securities> oSecurityMaster { get; set; }

}

All these three have these two values 1. ID 2. Name (In this case for Role - ID, RoleName | for Securities - ID, SecurityName ...) //add 3rd property of type bool isselected in order to work eith checkboxes only then you will get it posted back These don't have any boolean values

By using this ViewModel I'm binding these items using the below method...

public ActionResult AddingRoleSecurity()
{        
    ListRoles = new List<Roles>();
    ListSecurities = new List<Securities>();  //And then populate them with data ...

    var model = new ViewModel_Role_Security();
    model.oRoleMaster = ListRoles;
    model.oSecurityMaster = ListSecurities;
    return View(model);
}

My corresponding cshtml file is..

@model KnackWFM.BusinessEntities.ViewModel_Role_Security

@using (Html.BeginForm())
{
    <div class="contentsecurity">

        <div class="User_role">
            <p class="Security_role">User Role</p>

            @for (int i = 0; i < Model.oRoleMaster.Count; i++)
            {
                <input id="@Model.oRoleMaster[i].RoleID" name="@Model.oRoleMaster[i].RoleName" type="checkbox" value="@(Model.oRoleMaster[i].RoleName)" />
                <label for="@Model.oRoleMaster[i].RoleID">@Model.oRoleMaster[i].RoleName</label>
                <br />
                @Html.CheckBoxFor(Model.oRoleMaster[i].RoleID.selec)
            }

        </div>

        <div class="User_Page">
            <p class="Security_role">Role Security</p>

            @for (int i = 0; i < Model.oSecurityMaster.Count; i++)
            {
                <input id="@Model.oSecurityMaster[i].SecurityID" name="@Model.oSecurityMaster[i].SecurityName" type="checkbox" value="@(Model.oSecurityMaster[i].SecurityName)" />
                <label for="@Model.oSecurityMaster[i].SecurityID">@Model.oSecurityMaster[i].SecurityName</label>
                <br />
            }

        </div>
        <div class="bottombuttonsecurity">
            <button type="submit" id="btnSave" name="Command" value="Save" style="background-color: #3d3c4c;border-radius: 8px;color: white;padding: 5px;border: 1px solid #3d3c4c;">Save</button>
        </div>
    </div>
}

For which I get the following output, enter image description here

I would want to get the checked values as a model.

I have a HttpPost method like this, but it returns null values.

[HttpPost]
public ActionResult AddingRoleSecurity(ViewModel_Role_Security model)
{
    return View();
}

Please let me know how do I get the checked in values in the model?

Thank you very much!

like image 340
indiaxxo Avatar asked Dec 18 '14 09:12

indiaxxo


People also ask

Does MVC use data binding?

MVC doesn't use data bindings like old web api. You have to use model bindings in a MVC or MVVM approach.

What is two way binding MVC?

In two-way data binding, any changes in the Model gets reflected in the View and similarly any changes in the View gets reflected in the View automatically. This is done using attribute bind.

What is bind property in MVC?

Model binding allows you map request parameters to actions. This means action methods will have one or more parameters and those parameters will receive their values from the model binding framework.


2 Answers

Just to flesh out my comment above...

For a checkboxList - the viewmodel should include both an identifier property, and boolean selected property. If it doesn't already then either extend or create a new ViewModel class to fulfil this purpose - map your existing model to this specific viewmodel.

i.e. - Your Model Class(es)

public class UserRole
{
  public int RoleID {get; set;}
  public string RoleName {get; set;}
  public bool Selected {get; set;}
}

public class UserSecurity
{
  public int SecurityID {get; set;}
  public string SecurityName {get; set;}
  public bool Selected {get; set;}
}

public class UserRoleAndSecurityModel
{
  public List<UserRole> RoleMaster {get; set;}
  public List<UserSecurity> SecurityMaster {get; set;}
}

Your View: Note that in addition to the checkboxes Html.HiddenFor()has been included for each of the UserRole/UserSecurity ID properties, which allows MVC to bind the ID properties after postback.

@model UserRoleAndSecurityModel   

@using (Html.BeginForm())
{
    <div class="contentsecurity">  
        <div class="User_role">
            <p class="Security_role">User Role</p>

            @for (int i = 0; i < Model.RoleMaster.Count; i++)
            {
                @Html.CheckBoxFor(m => m.RoleMaster[i].Selected)
                @Html.HiddenFor(m => m.RoleMaster[i].RoleId)
                @Html.LabelFor(m => m.RoleMaster[i].Selected, 
                                    Model.RoleMaster[i].RoleName)
                <br />
            }
        </div>

        <div class="User_Page">
            <p class="Security_role">Role Security</p>

            @for (int i = 0; i < Model.SecurityMaster.Count; i++)
            {
                @Html.CheckBoxFor(m => m.SecurityMaster[i].Selected)
                @Html.HiddenFor(m => m.SecurityMaster[i].SecurityId) 
                @Html.LabelFor(m => m.SecurityMaster[i].Selected, 
                                    Model.SecurityMaster[i].SecurityName)
                <br />

            }
        </div>
        <div class="bottombuttonsecurity">
            <button type="submit" id="btnSave" name="Command" value="Save" style="background-color: #3d3c4c;border-radius: 8px;color: white;padding: 5px;border: 1px solid #3d3c4c;">Save</button>
        </div>
    </div>

and your controller should now use the new model above too!

like image 85
James S Avatar answered Oct 23 '22 12:10

James S


I don't want to appear like I'm taking credit for James excellent work, but a new answer is all I can do. For reasons I do not understand, my edit that corrected compile errors in the code were rejected as not correcting critical issues. So I post this as a complete working answer.

The Models:

public class UserRole
{
  public int RoleID {get; set;}
  public string RoleName {get; set;}
  public bool Selected {get; set;}
}

public class UserSecurity
{
  public int SecurityID {get; set;}
  public string SecurityName {get; set;}
  public bool Selected {get; set;}
}

public class UserRoleAndSecurityModel
{
  public List<UserRole> RoleMaster {get; set;}
  public List<UserSecurity> SecurityMaster {get; set;}
}

And the view:

@model UserRoleAndSecurityModel   

@using (Html.BeginForm())
{
    <div class="contentsecurity">  
        <div class="User_role">
            <p class="Security_role">User Role</p>

            @for (int i = 0; i < Model.RoleMaster.Count; i++)
            {
                @Html.CheckBoxFor(m => m.RoleMaster[i].Selected)
                @Html.HiddenFor(m => m.RoleMaster[i].RoleId)
                @Html.LabelFor(m => m.RoleMaster[i].Selected, 
                                    Model.RoleMaster[i].RoleName)
                <br />
            }
        </div>

        <div class="User_Page">
            <p class="Security_role">Role Security</p>

            @for (int i = 0; i < Model.SecurityMaster.Count; i++)
            {
                @Html.CheckBoxFor(m => m.SecurityMaster[i].Selected)
                @Html.HiddenFor(m => m.SecurityMaster[i].SecurityId) 
                @Html.LabelFor(m => m.SecurityMaster[i].Selected, 
                                    Model.SecurityMaster[i].SecurityName)
                <br />

            }
        </div> 

        <div class="bottombuttonsecurity">
            <button type="submit" id="btnSave" name="Command" value="Save" style="background-color: #3d3c4c;border-radius: 8px;color: white;padding: 5px;border: 1px solid #3d3c4c;">Save</button>
        </div>
    </div>
like image 34
Red Avatar answered Oct 23 '22 10:10

Red