3

I've inherited my first MVC project and it involves using MVC3 on top of Linq to SQL. I've been trying to find a way to generate a check box list based on a many to many relationship involving a cross table.

I have a systemFailureType table that maps to a SystemFailureProblem table via a cross table.

Here is my designer layout for the tables:

enter image description here

here my view model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using XNet.Repository.Model;

namespace XNet.WebUI.Hotel.ViewModel
{
    public class CheckFacilityVM
    {
        public int FacilityID { get; set; }
        public string facilityName { get; set; }
        public bool facilityAvailable { get; set; }

        public virtual Facility facility { get; set; }
        public virtual HotelFacility hotelfacility { get; set; }
    }
}

here my controller

public ActionResult Facility()
        {
            ViewBag.hotel = _hotelService.GetByID(1).HotelName;

            var model = db.Facilities
                        .Select(htl => new CheckFacilityVM
                        {
                            FacilityID = htl.FacilityID,
                            facilityName = htl.FacilityName,
                            facilityAvailable = htl.IsActive,
                        })
                        .ToList();

            return View(model);
        }

and here my constructor

public Facility ShowRoomFacility(int HotelID)
        {
            var x = (from d in db.Facilities
                     where d.FacilityID == HotelID
                     select d).FirstOrDefault();

            return x;
        }

how can i make this.....

1 Answer 1

2

I'll provide you a simple, more common example that you can adapt for your purposes - Users and Roles (a user can be assigned to many roles and likewise a role can have many users).

Assume we have an "Update User" form where we want to set the roles the user belongs to.

Here's what the controller/view model would look like:

public class UsersController : Controller {

    [HttpGet]
    public ActionResult Update(int id) {
        var user = db.Users.Find(id);
        var model = new UsersUpdateModel {
            Name = user.Name,
            SelectedRoles = user.Roles.Select(r => r.Id).ToList(),
            Roles = GetRolesSelectList()
        };

        return View(model);
    }

    [HttpPost]
    public ActionResult Update(UsersUpdateModel model) {
        var user = db.Users.Find(model.Id);

        var roles = db.Roles.ToList();

        foreach (var role in roles) {
            if (model.SelectedRoles.Contains(role.Id)) {
                user.AddRole(role);
            }
            else {
                user.RemoveRole(role);
            }
        }
    }

    public SelectList GetRolesSelectList() {
        var roles = db.Roles.OrderBy(r => r.Name).ToList();
        return new SelectList(roles, "Id", "Name");
    }
}

public class UsersUpdateModel {
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<int> SelectedRoles { get; set; }
    public SelectList Roles { get; set; }
}

Essentially you need to add a property to your view model to hold the available roles (in this example, "Roles") and one to hold the selected roles (in this example, "SelectedRoles").

In your POST action you can then load all the roles and, if the Id exists in UsersUpdateModel.SelectedRoles you add the role to the user, otherwise you remove it.

I tend to encapsulate the process of adding/removing the Role (or whatever collection it may be) in the side that owns the relationship - for example, User.AddRole would probably check to see if the role already exists to prevent adding it twice:

public void AddRole(Role role) {
    var exists = this.Roles.FirstOrDefault(r => r.Id == role.Id);

    if (exists == null) {
        Roles.Add(role);
    }
}

Finally to create the Checkbox list you can use the helper I created here. It would look something like:

@Html.CheckBoxListFor(model => model.SelectedRoles, Model.Roles)

That should give you enough to go on. Note that the code was written in notepad so is probably not copy/pastable.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.