Single Fighter Single Fighter - 3 months ago 9
C# Question

How to know the selected checkboxes from within the HttpPost Create action method?

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?

Answer

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.

public class SelectedCourse
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSelected { get; set; }
}

public class StudentCourseVM
{
    public int StudentId { set; get; }       
    public IEnumerable<SelectedCourse> SelectedCourses { get; set; }
}

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 name SelectedCource.cshtml

enter image description here Paste this code to the new file

@model SelectedCourse
<label>@Model.Name</label>
<input asp-for="IsSelected"/>
<input type="hidden" asp-for="Id" />

Now in your GET action, create an object of the view model, load the SelectedCourses collection and send it to the view.

public IActionResult Create()
{
    // I hard coded the student id and the courses here.
    // you may replace it with real data.
    var vm = new StudentCourseVM { StudentId = 12 }; 
    //Assuming we are assigning courses to the student with id 12
    vm.SelectedCourses = new List<SelectedCourse>()
    {
        new SelectedCourse {Id = 1, Name = "CSS"},
        new SelectedCourse {Id = 2, Name = "Swift"},
        new SelectedCourse {Id = 3, Name = "IOS"},
        new SelectedCourse {Id = 4, Name = "Java"}
    };
    return View(vm);
}

Now in your main view(Create.cshtml) which is strongly typed to StudentCourseVM,Use EditorFor helper method on the SelectedCourses property.

@model StudentCourseVM
<form asp-action="Create">   
    @Html.EditorFor(f=>f.SelectedCourses)
    <input type="hidden" asp-for="StudentId"/>
    <input type="submit"/>
</form>

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 the IsSelected property value. The courses user selected in the ui will have a true value.

[HttpPost]
public IActionResult Create(StudentCourseVM model)
{
    var studentId = model.StudentId; 
    foreach (var modelSelectedCourse in model.SelectedCourses)
    {
        if (modelSelectedCourse.IsSelected)
        {
            //this one is selected. Save to db
        }
    }
    // to do : Return something
}

enter image description here

Comments