Asp.Net Mvc Checkbox list

11,694

Create a custom 'services check box item' class (reusable), and make a list or enumerable of them as a property in your AdditionalServicesModel. Also, its probably a better idea to create a constructor of the model so you don't have to assign the model properties inside the controller.

public class ServicesItem
{
     public bool Selected { get; set; }
     public string Value { get; set; }
     public string Text { get; set; }
}

public class AdditionalServicesModel
{
    public AdditionalServicesModel(IList<ServicesItem> items){
         this.AdditionalServices = items;
    }

    public IList<ServicesItem> AdditionalServices { get; set; }
}

Create a custom editor template for Additional Services, to easily reference in your view (you don't have to add a hidden for the text, as only the value and selected properties will be default binded back to the model:

  @Html.CheckBoxFor(m => Selected)
  @Html.LabelFor(m => Text)
  @Html.HiddenFor(m => Value)

Then pop the editor template into your view (let MVC.net do its magic - have a look at the markup to see what it does):

@Html.EditorFor(m => m.AdditionalServices)

Then inspect the automatically bound values in your controller:

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            List<SelectListItem> services = new List<SelectListItem>();
            services.Add(new SelectListItem { Text = "service-1", Value = "1", Selected=false });
            services.Add(new SelectListItem { Text = "service-2", Value = "2", Selected=false });
            services.Add(new SelectListItem { Text = "service-3", Value = "3", Selected=false });

            return View(new AdditionalServicesModel(services));
        }

    [HttpPost]
    public ActionResult Index(AdditionalServicesModel result)
    {
         var selectedServicesList = result.AdditionalServices.Where(s => s.Selected);
         return RedirectToAction("Thanks", "Home");
    }
}
Share:
11,694
Alex
Author by

Alex

Updated on July 03, 2022

Comments

  • Alex
    Alex almost 2 years

    I'm implementing check box list in MVC, although I succeed to get the desired result, I have a doubt in my approach:

    public class AdditionalServicesModel
    {
        public IList<SelectListItem> AdditionalServices { get; set; }
    }
    

    =========================================================================

    public class HomeController : Controller
    {
        //
        // GET: /Home/
    
        public ActionResult Index()
        {
            AdditionalServicesModel objAdditionalServicesModel = new AdditionalServicesModel();
    
            List<SelectListItem> services = new List<SelectListItem>();
            services.Add(new SelectListItem { Text = "service-1", Value = "1", Selected=false });
            services.Add(new SelectListItem { Text = "service-2", Value = "2", Selected=false });
            services.Add(new SelectListItem { Text = "service-3", Value = "3", Selected=false });
            objAdditionalServicesModel.AdditionalServices = services;
    
            return View(objAdditionalServicesModel);
        }
    
        [HttpPost]
        public ActionResult Index(AdditionalServicesModel result)
        {
            return RedirectToAction("Thanks", "Home");
        }
    
        public ActionResult Thanks()
        {
            return View();
        }
    }
    

    =========================================================================

    @model checkboxes.Models.AdditionalServicesModel
    @{
        ViewBag.Title = "Index";
        Layout = null;
    }
    
    
    @using (Html.BeginForm("Index", "Home", FormMethod.Post))
    {
        for (int i = 0; i < Model.AdditionalServices.Count; i++)
        {        
            <ul>
                <li>
                    @Html.CheckBoxFor(m=>Model.AdditionalServices[i].Selected, new { id = "Chk-" + i})
                    @Html.Label(Model.AdditionalServices[i].Text, new { @for = "Chk-" + i })
                    @Html.HiddenFor(m => Model.AdditionalServices[i].Text)
                    @Html.HiddenFor(m=> Model.AdditionalServices[i].Value)
                </li>
            </ul>
        }
        <input type="submit" value="POST to Controller" />
    }
    

    1) For one checkbox I should create 2 additional hidden fields. Is there a better approach? I feel like it just wrong to make all this long way just to send checkboxes values + names, It would be much easier to collect its values with javascript and send it via Json, but then I will not have an unobtrusive validation...

    2) I send all check boxes while I need to send only selected boxes. Is there a way to do it with forms post?