I have many-to-many relationship between Student
and Course
. The linking entity set is Enrollment
. For the sake of simplicity, they are all defined as follows.
Models
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
public class Enrollment
{
public int Id { get; set; }
public int StudentId { get; set; }
public int CourseId { get; set; }
public virtual Student Student { get; set; }
public virtual Course Course { get; set; }
}
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
ViewModels
public class StudentCourseVM
{
public Student Student { get; set; }
public IEnumerable<Course> SelectedCourses { get; set; }
public IEnumerable<Course> AvailableCourses { get; set; }
}
Controllers
public IActionResult Create()
{
var availableCourses = context.Courses;
return View(new StudentCourseVM { AvailableCourses = availableCourses });
}
[HttpPost]
public async Task<IActionResult> Create(StudentCourseVM sc)
{
if (ModelState.IsValid)
{
// What should I do here?
// ======================
await context.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(sc);
}
Views
@model MasterDetails.ViewModels.StudentCourseVM
<form asp-action="Create">
<div>
<label asp-for="@Model.Student.Name"></label>
<input asp-for="@Model.Student.Name" />
</div>
<div>
<label asp-for="@Model.Student.Enrollments"></label><br />
@foreach (var course in Model.AvailableCourses)
{
<input type="checkbox" name="@course.Title" id="@course.Id" /> @course.Title <br />
}
</div>
<input type="submit" value="Create" />
</form>
Questions
How to know the selected check boxes from within the HttpPost Create
action method?
You can use Editor Templates to do this.
First, create a new class for the course selection and update your view model to have a collection of that class.
You do not need to copy and paste all the properties from your entity model to your view model. View model needs only those properties which the view absolutely need. I am assuming you want to assign courses to a specific student
Now go to your
~/Views/YourControllerName
and create a directory called EditorTemplates. Create a new razor file there and give the nameSelectedCource.cshtml
Paste this code to the new file
Now in your GET action, create an object of the view model, load the SelectedCourses collection and send it to the view.
Now in your main view(
Create.cshtml
) which is strongly typed to StudentCourseVM,UseEditorFor
helper method on theSelectedCourses
property.The Editor template will execute code in the editor template file for each item in the SelectedCourses collection. So you will have the course name and a checkbox visible to the user.
In your HttpPost action method, you can use the same view model as the parameter. When the form is submitted, you may loop through the items in
SelectedCourses
property check theIsSelected
property value. The courses user selected in the ui will have atrue
value.Pre-selecting some checkboxes on page load
Sometimes you want to pre select some checkboxes when the page loads (Ex : For your edit screen you want to show already saved courses as checked). To do this, you simply need to set the
IsSelected
property of the correspondingSelectedCourse
object to true in your GET action method.The above code will pre select the checkboxes for Swift and IOS.