简体   繁体   中英

How to get the values of the checked items of checkboxes in MVC5?

I have a view model which includes an ICollection field, something like this:

public class BusinessViewModel
{
    ...

    public virtual ICollection<Subcategory> Subcategories { get; set; }

    ...
}

Then, in my actual view, I have a code segment like this:

<div class="form-group">
    @Html.LabelFor(model => model.Subcategories, "Subcategory", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        <span id="subcats">

        </span>
    </div>
</div>

Afterwards, I have an AJAX call in JS, which simply populates my subcats span field with checkbox items, and my AJAX call looks like this:

$("#CategoryID").change(function () {
    $("#subcats").empty();

    $.ajax({
        type: 'POST',
        url: '/Account/GetSubcategories',
        dataType: 'json',
        data: { id: $("#CategoryID").val() },
        success: function (subcategories) {
            $.each(subcategories, function (i, subcategory) {
                $("#subcats").append('<input type="checkbox" name="' + subcategory.value + '" value="' + subcategory.id + '" />' + subcategory.value + '<br />');
            });
        },
        error: function (ex) {
            console.log('Failed to retrieve subcategories! ' + ex);
        }
    });

    return false;
});

The point is that, it works all fine in the view, but when I check the items I wish and press the button in order to submit the form, I get an error message saying that a NullReferenceException occurred, when I reach the foreach statement of the below code in my controller:

    public async Task<ActionResult> RegisterBusiness(BusinessViewModel model)
    {
        if (ModelState.IsValid)
        {
            ...

            foreach (var subcategory in model.Subcategories)
            {
                db.Entry(subcategory).State = EntityState.Unchanged;
                user.Subcategories.Add(subcategory);
            }

            ...
        }
        ...
     }

I guess this is due to the fact I don't assign the selected checkboxes to my model. Can someone, tell me how can I do it in my current setup? A code example where this is achieved would be highly welcomed.

EDIT: This is how my subcategory model looks like, at least important part of it:

public class Subcategory
{
    public int SubcategoryID { get; set; }
    public string SubcategoryName { get; set; }
}

And also according to the answer below my view now includes this:

<div class="form-group">
    @Html.LabelFor(model => model.Subcategories, "Subcategory", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.ListBoxFor(model => model.SelectedSubcategories, Model.SubcategoryList)
    </div>
</div>

I get a NullReference error again in the ListBoxFor part.

Your SubCategories are null because you are not posting back an values relating to SubCategories . The following example is based on using a multi-select list to choose the sub categories (unchecked checkboxes do not post back, so using checkboxes is much more difficult)

First create a property in you view model that binds to the selected sub categories. You may also want a SelectList property to render the initial sub categories to display

public int[] SelectedSubCategories { get; set; }
public SelectList SubCategoryList { get; set; }

and in the view, render the select

@Html.ListBoxFor(m => m.SelectedSubCategories, Model.SubCategoryList)

then modify your script

$("#CategoryID").change(function () {
  $("#SelectedSubCategories").empty();
  var url = '@Url.Action("GetSubcategories", "Account")';
  $.get(url, { id: $("#CategoryID").val() }, function(subcategories) {
    $.each(subcategories, function (i, subcategory) {
      var option = $('<option></option>');
      option.val(subcategory.id);
      option.text(subcategory.value);
      $("#SelectedSubCategories").append(option);
    });
  });
});

When posting back, the value of SelectedSubCategories now contains the ID's of each selected sub category

public async Task<ActionResult> RegisterBusiness(BusinessViewModel model)
{
  foreach (int ID in model.SelectedSubCategories)
  {

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