0

I have 3 multiselect dropdown lists. When I make multiple selections from each dropdown lists and submit I can see that the results are being posted but doesn't get passed to the controller.

my view

    @model Facility.AdgarWeb.ViewModels.MailingConfigVM

    @using (Html.BeginForm("New", "MailingConfig"))
    {
@*Company List Dropdown*@
<div class="mailingConfiguration__modal__dropDown mailingConfiguration__modal__dropDown--companyList">
    <h3 class="mailingConfiguration__modal__dropDown__title">Wybierz Budynki</h3>
    <div class="dropdown companiesDropdown">
        <button class="btn btn-secondary dropdown-toggle" type="button" id="companiesButton" aria-haspopup="true" aria-expanded="false">
            Select Building
        </button>
        @Html.LabelFor(m => m.allBuildings)
        @Html.DropDownListFor(m => m.allBuildings, new MultiSelectList(Model.allBuildings, "Id", "Name"), new { @class="dropdown-menu", @multiple="true" })
    </div>
</div>

@*Classification List Dropdown*@
<div class="mailingConfiguration__modal__dropDown mailingConfiguration__modal__dropDown--classificationList">
    <h3 class="mailingConfiguration__modal__dropDown__title">Wybierz Klasyfikacje</h3>
    <div class="dropdown classificationDropdown">
        <button class="btn btn-secondary dropdown-toggle" type="button" id="classificationButton" aria-haspopup="true" aria-expanded="false">
            Select Classification
        </button>
        @Html.LabelFor(m => m.allServices)
        @Html.DropDownListFor(m => m.allServices, new MultiSelectList(Model.allServices, "Id", "Name"), new { @class = "dropdown-menu", @multiple = "true" })
    </div>
</div>
@*Users List Dropdown*@
<div class="mailingConfiguration__modal__dropDown mailingConfiguration__modal__dropDown--usersList">
    <h3 class="mailingConfiguration__modal__dropDown__title">Wybierz Użytkowników</h3>
    <div class="dropdown usersDropdown">
        <button class="btn btn-secondary dropdown-toggle" type="button" id="usersButton" aria-haspopup="true" aria-expanded="false">
            Select Users
        </button>
        @Html.LabelFor(m => m.allUsers)
        @Html.DropDownListFor(m => m.allUsers, new MultiSelectList(Model.allUsers, "Id", "UserName"), new { @class = "dropdown-menu", @multiple = "true" })
    </div>
</div>

<input type="submit" class="btn btn-primary" name="New" value="Submit">
}

viewmodel

    public class MailingConfigVM
{
    [Display(Name = "Buildings")]
    public IEnumerable<Building> allBuildings { get; set; }

    [Display(Name = "Services")]
    public IEnumerable<Facility.Model.Service> allServices { get; set; }

    [Display(Name = "Users")]
    public IEnumerable<User> allUsers { get; set; }

}

controller

        public ActionResult Create()
    {
        if (!SessionControlService.CheckIsLoginStillTrue(_loginsService, HttpContext))
            return RedirectToAction("Login", "Account");

        MailingConfigVM vm = new MailingConfigVM();
        vm.allBuildings = _buildingService.GetBuildings();
        vm.allServices = _serviceService.GetServices();
        vm.allUsers = _userService.GetUsers().Where(user => user.Roles.Any(r => r.Id <= 4));
        var buildings = _buildingService.GetBuildings().ToList();
        return View(vm);
    }
    [Authorize(Roles = "Admin")]
    [HttpPost]
    public ActionResult New(MailingConfigVM mailingConfigVM)
    {
        if (!SessionControlService.CheckIsLoginStillTrue(_loginsService, HttpContext))
            return RedirectToAction("Login", "Account");
        if (!User.IsInAnyRoles("Admin"))
            return RedirectToAction("Index");

        return RedirectToAction("Create", "MailingConfig");
    }

The create controller populates the forms with datas for selection and New controller is httppost. I want the selected items to be passed to this controller, but after POST the result is "COUNT=0" on each of the list.

I would appreciate any help.

akyj
  • 71
  • 2
  • 9

1 Answers1

2

You cannot bind a<select multiple> to a collection of complex objects, which is what your properties are. A <select multiple> posts back an array of simple values.

Your model needs 3 additional properties (note this assumes that the Id properties of your Building, Service and User model are typeof int)

public IEnumerable<int> SelectedBuildings { get; set; }
public IEnumerable<int> SelectedServices { get; set; }
public IEnumerable<int> SelectedUsers { get; set; }

In addition, you should be making the collection properties IEnumerable<SelectListItem>, and using new SelectList(...) in the controller, not the view to create the options, for example

public IEnumerable<SelectListItem> AllBuildings { get; set; }
....

and in the controller

vm.AllBuildings = new SelectList(_buildingService.GetBuildings(), "Id", "Name");

Finally, in order to bind correctly, you must use ListBoxFor(), not DropDownListFor() as explained in Why does the DropDownListFor lose the multiple selection after Submit but the ListBoxFor doesn't?

Your view code will now be

@Html.LabelFor(m => m.SelectedBuildings)
@Html.ListBoxFor(m => m.SelectedBuildings, Model.AllBuildings, new { @class="dropdown-menu" })
....
@Html.ListBoxFor(m => m.SelectedServices, Model.AllServices, new { @class="dropdown-menu" })
....