简体   繁体   中英

How to HTTPPost ASP.Net MVC 5 CheckBoxList to database

I am having trouble getting the values to post to my database table from a checkboxlist. Here are my models:

public partial class SecurityChange_Access
{
    public int ID { get; set; }
    public string Access_Name { get; set; }
    public bool IsSelected { get; set; }
}

public partial class Change
{
    public int ID { get; set; }
    public string Emp_FirstName { get; set; }
    public string Emp_LastName { get; set; }
    public string Emp_Supervisor { get; set; }
    public string Emp_MangerEmail { get; set; }
    public string Emp_MirrorAccount { get; set; }
    public string Security_Change_Access { get; set; }

    public List<SecurityChange_Access> SecurityAccessList { get; set; }

    public bool addAccess { get; set; }
    public IEnumerable<SelectListItem> ChangeRadioList { get; set; }

    //[Required(ErrorMessage = "You must select an option for TestRadio")]
    public String ChangeRadio { get; set; }
}

public class bTest
{
    public int ID { get; set; }
    public string Name { get; set; }
}

Here is the HTTPGet and HTTPPost:

[HttpGet]
public ActionResult Change(Change change)
{   
    List<bTest> list = new List<bTest>();
    list.Add(new bTest() { ID = 1, Name = "Add Access" });
    list.Add(new bTest() { ID = 2, Name = "Remove Access" });
    list.Add(new bTest() { ID = 3, Name = "Change Access" });
    SelectList sl = new SelectList(list, "Name", "Name");
    change.ChangeRadioList = sl;

    List<ActiveDirectory> objadlist = (from data in       objentity.ActiveDirectories select data).ToList();
    ActiveDirectory objAD = new ActiveDirectory();
    objAD.displayName = "";
    objAD.mail = "";
    objAD.Id = 0;
    objadlist.Insert(0, objAD);
    SelectList objmodeldata = new SelectList(objadlist, "displayName", "displayName", 0);
    /*Assign value to model*/
    change.ADList = objmodeldata;

    change.SecurityAccessList = new List<SecurityChange_Access>();
    change.SecurityAccessList = BindSecurity();

    return View(change);
}

public List<SecurityChange_Access> BindSecurity()
{
    List<SecurityChange_Access> _objsecurity = (from data in _entities.SecurityChange_Access select data).ToList();
    return _objsecurity;
}

[HttpPost]
public ActionResult Change([Bind(Include = "ID, Emp_FirstName, Emp_LastName, Emp_Supervisor, Emp_MangerEmail, Emp_MirrorAccount, Security_Change_Access, Security_Access_To_1, Security_Access_To_2, Security_Access_To_3, Security_Access_To_4, Security_Access_To_5, Security_Access_To_6, Security_Access_To_7, Security_Access_To_8, Security_Access_To_9, Security_Access_To_10, Security_Access_To_Other, Security_Access_ADF_Mirror, Security_Access_JDE_Mirror, Security_Access_NetworkDrives_1, Security_Access_NetworkDrives_2, Security_Access_NetworkDrives_3, Security_Access_NetworkDrives_4, Security_Access_NetworkDrives_5, Security_Access_NetworkDrives_6, Security_Access_NetworkDrives_7, Security_Access_NetworkDrives_8, Security_Access_NetworkDrives_9, Security_Access_NetworkDrives_10, Security_Access_NetworkDrives_11, Security_Access_NetworkDrives_12, Security_Access_NetworkDrives_13, Security_Access_NetworkDrives_14, Security_Access_NetworkDrives_15, Security_Access_NetworkDrives_16, Security_Access_NetworkDrives_17, Security_Access_NetworkDrives_18, Security_Access_NetworkDrives_19, Security_Access_NetworkDrives_20, Security_Access_NetworkDrives_21, Security_Access_NetworkDrives_22, Security_Access_NetworkDrives_23, Security_Access_NetworkDrives_24, Security_Access_NetworkDrives_25, Security_Access_NetworkDrives_26, Security_Access_NetworkDrives_27, Security_Access_NetworkDrives_28, Security_Access_NetworkDrives_29, Security_Access_NetworkDrives_30, IT_Equipment_1, IT_Equipment_2, IT_Equipment_3, IT_Equipment_4, IT_Equipment_5, IT_Equipment_6, IT_Equipment_7, IT_Equipment_8, IT_Equipment_9, IT_Software_1, IT_Software_2, IT_Software_3, IT_Software_4, IT_Software_Other, IT_Media_1, IT_Media_2, IT_Media_3, IT_Media_Other, IT_Other_Equipment, Additional_Information")] Change change, int? id)
{
    try
    {
        if (ModelState.IsValid)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("SELECTED COUNTRY :- ").AppendLine();
            foreach (var item in change.SecurityAccessList)
            {
                if (item.IsSelected == true)
                {
                    sb.Append(item.Access_Name + ", ").AppendLine();
                    _entities.Changes.Add(change);
                    _entities.SaveChanges();

                    return RedirectToAction("Change");
                }
            }

        }

    }
    catch (System.Data.Entity.Validation.DbEntityValidationException ex)
    {
         foreach (var e in ex.EntityValidationErrors)
        {
            //check the ErrorMessage property
        }
    }
    return View(change);
}

Here is the Razor code:

<table border="0" width="1000" cellpadding="5" cellspacing="5">
    @for (int i = 0; i < Model.SecurityAccessList.Count; i++)
    {
        <tr>
            <td width="200">
                @Html.CheckBoxFor(m => Model.SecurityAccessList[i].IsSelected)
                @Model.SecurityAccessList[i].Access_Name
                @Html.HiddenFor(m => Model.SecurityAccessList[i].ID)
                @Html.HiddenFor(m => Model.SecurityAccessList[i].Access_Name)
            </td>
        </tr>
    }

In my HTTPGET I am binding my list but then I need to post my list on the checked values. I am not sure how to go about doing this. I am also having problems getting the checked list so it is comma separated. I can't seem to find anything online that can help me with this. I just can't seem to be able to post the data to the Security_Change_Access field.

Firstly, do not pass a complex object as a parameter to a GET method. Properties that are complex objects or collections will not bind (they will be null), you may exceed the query string limit (crashing your app) and then there the ugly url it creates. Just initialize a new Change in the method, or pass an ID and get the Change based on the ID .

Your view code looks OK although I suggest you use a label associated with the checkbox and the hidden input for the Access_Name property seems unnecessary

@for (int i = 0; i < Model.SecurityAccessList.Count; i++)
{
  @Html.CheckBoxFor(m => m.SecurityAccessList[i].IsSelected)
  @Html.LabelFor(m => m.SecurityAccessList[i].IsSelected, Model.SecurityAccessList[i].Access_Name)
  @Html.HiddenFor(m => m.SecurityAccessList[i].ID)
}

which should generate html with name attribute like

<input type=checkbox" name="SecurityAccessList[0].IsSelected" ...>
<input type=checkbox" name="SecurityAccessList[1].IsSelected" ...>

Next, remove the (awful) [Bind] attribute. By default, all properties are bound, which seems to be what you want to do, but in fact you have excluded SecurityAccessList (I think - tl;dr ) and included a whole lot of 'properties' that don't even exist in your model ( Security_Access_To_1, Security_Access_To_2, ..... ). If you ever find your self needing to use [Bind(Include="..")] , stop and use a view model to display/edit what you need instead.

The POST method should then correctly bind your model with change.SecurityAccessList containing the collection. Note I recommend you change your parameter to (say) model . In this case its OK, but there are plenty of question on SO about binding failing because the name of the parameter match the name of a model property.

Side notes:

The List<bTest> list = new List<bTest>(); bit where you create a SelectList for what seems to be used in a radio button list seems odd. A select list is not even appropriate for that usage and in any case your not even using the ID property of bTest . It may just as well be

SelectList sl = new SelectList(new List<string>() { "Add Access", "Remove Access", "Change Access" });

which produces exactly the same result, although I suspect all you need is the property to be List<string>

Next the ActiveDirectory objAD = new ActiveDirectory(); bit where your seem to be inserting a 'default' or null item for use in a select list is also wrong. Again the only property you use is displayName but in any case delete it and use the overload of DropDownListFor() that accepts optionLabel

@Html.DropDownListFor(m => m.YourProperty, Model.ADList, "-Please select-")

This adds a null option <option value>-Please Select-</option> which can be used in association with the [Required] attribute.

Finally there the code inside the if (ModelState.IsValid) block which makes no sense. You don't even use the value of sb (not sure what its even for) and then your attempting to add the same instance of change into the database each time IsSelected=true , except that its only added once because as soon as it is added, you do a redirect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM