Brian Brian Brian Brian - 1 month ago 9
ASP.NET (C#) Question

ASP.NET MVC Insert CheckBoxList values to Database

I'm having trouble understanding how to add my CustId and selected DevId values from the CheckBoxList to my CustomerDevice table in my database.

My Index Action Method for the CustomerDeviceController displays a list of Customers from my Customers table. I have a link labeled "Add Device(s)" that passes the CustId value to the CustomerDeviceController [HttpGet] Create Action Method which displays my CheckBoxListItem values from the Devices table which works fine.

The part that I'm having trouble understanding and figuring out, is how can I add the selected DevId values from the CheckBoxList along with the CustId value to my CustomerDevice Table on the [HttpPost] Create Action Method.

Please see the following code below that I have so far.

CheckBoxListItem Model

public class CheckBoxListItem
{
public int ID { get; set; }
public string Display { get; set; }
public bool IsChecked { get; set; }
}


Customer Model

public class Customer
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public string CustFirstName { get; set; }
public string CustLastName { get; set; }
public string CustCompanyName { get; set; }
public string CustAddress { get; set; }
public string CustPhoneNumber { get; set; }
public string CustMobileNumber { get; set; }
public string CustEmailAddress { get; set; }
}


Device Model

public class Device
{
public int DevId { get; set; }
public string DevType { get; set; }
}


CustomerDevice Model

public class CustomerDevice
{
public int CustId { get; set; }
public int DevId { get; set; }

public Customer Customer { get; set; }
public Device Device { get; set; }
}


Shared/EditorTemplates/CheckBoxListItem.cshtml

<div class="checkbox">
<label>
@Html.HiddenFor(x => x.ID)
@Html.CheckBoxFor(x => x.IsChecked)
@Html.LabelFor(x => x.IsChecked, Model.Display)
</label>
<br />




CustomerDeviceFormViewModel

public class CustomerDeviceFormViewModel
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public List<CheckBoxListItem> Devices { get; set; }
}


CustomerDeviceController

public class CustomerDeviceController : Controller
{
private CheckBoxAppContext db;

public CustomerDeviceController(CheckBoxAppContext context)
{
db = context;
}


// GET: /<controller>/
public IActionResult Index()
{
return View(db.Customers.ToList());
}


public ActionResult Create(int? id)
{
if (id == null)
{
return NotFound();
}

var customervm = new CustomerDeviceFormViewModel();
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);

if (customer == null)
{
return NotFound();
}

customervm.CustId = customer.CustId;

// Retrieves list of Devices for CheckBoxList
var deviceList = db.Devices.ToList();
var checkBoxListItems = new List<CheckBoxListItem>();
foreach (var device in deviceList)
{
checkBoxListItems.Add(new CheckBoxListItem()
{
ID = device.DevId,
Display = device.DevType,
IsChecked = false //On the create view, no devices are selected by default
});
}

customervm.Devices = checkBoxListItems;
return View(customervm);
}
}


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerDeviceFormViewModel vm)
{
if (ModelState.IsValid)
{
var customerDevices = new CustomerDevice();
{
customerDevices.CustId = vm.CustId;

var deviceList = db.Devices.ToList();
var checkBoxListItems = new List<CheckBoxListItem>();
foreach (var deviceId in deviceList)
{

}
}

db.CustomerDevices.Add(customerDevices);
db.SaveChanges();
return RedirectToAction("Index");
}

else
{
return View(vm);
}
}
}


Index View

<table class="table">
<tr>
<th>Id</th>
<th>Display Name</th>
<th>Actions</th>
</tr>

@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.CustId)
</td>
<td>
@Html.DisplayFor(modelItem => item.CustDisplayName)
</td>
<td>
@Html.ActionLink("Add Device(s)", "Create", new { id = item.CustId })
</td>
</tr>
}




Create View

<div class="form-group">
@Html.EditorFor(x => x.Devices)
</div>

@Html.HiddenFor(c => c.CustId)

<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>

Answer

Assuming that your CustomerDevice is the join table for a M:N relation between Customer and Device entities, I think you need something like this in your POST action:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CustomerDeviceFormViewModel vm)
{
    if (ModelState.IsValid)
    {
        foreach (var deviceId in vm.Devices.Where(x => x.IsChecked).Select(x => x.ID))
        {
            var customerDevices = new CustomerDevice
            {
                CustId = vm.CustId,
                DevId = deviceId
            };

            db.CustomerDevices.Add(customerDevices);
        }

        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(vm);
}

You create an entity of the join table and add it to the context. EF will associate the records when you call SaveChanges.

Hope this helps!