I'm working on the contoso university project, in the students section there's a section where the user can create a new student for the university. I'm trying to add a checkbox list of all the available courses so that the student can choose from, but I keep receiving this error when I try to open the Create page:
NullReferenceException: Object reference not set to an instance of an object
The repository is public I'm working on the file called "ContosoUniversity (ud) - Copy",
I will add now all the code I believe is linked to the issue:
Views > Students > Create.cshtml
<h4>Enroll in Courses</h4>
@* the syntax inside () defines the loop *@
@* the var course is used to represent every item in the collection and can be changed every loop *@
@* ViewData["AvialbleCourse"] this covers the data passed from the view to the controller, *@
@* it should receive a view bag from the controller which is named AvailableCourses *@
@foreach (var course in ViewData["AvailableCourses"] as List<Course>)
{
<div class="form-check">
@* type="checkbox" *@
@* this ensures the type of this input will be checkbox *@
@* name="selectedCourses": This sets the name attribute of the checkbox input.
When the form containing this input is submitted,
the selected checkboxes will be sent to the server under the name "selectedCourses". *@
@* name="selectedCourses": This sets the name attribute of the checkbox input.
When the form containing this input is submitted, the selected checkboxes will be sent to the server under the name "selectedCourses". *@
@* value="@course.CourseID"
the value attribute specifies the value that is sent to the server when the form is submitted
@course.CourseID
this is evalutaed on the server side, before the the HTML is sent to the client's browser
value=""
this sets the value of the input element
whatever value you assign to this attribute will be sent to the server when the form is submitted
so when the user check the checkbox assositated with a particular course,
the CourseID of that course is sent as part of the form data when the form is submitted
this allows the server-side code to know which course or coruses the user has selected
so the value of the courseID in the below input doesn't include all the CourseIDs
it loops with the loop and when the user checks one of them it is marked and sent to the server
as a chosen Course or as a chosen CourseID
*@
<input class="form-check-input" type="checkbox" id="@("course_" + course.CourseID)" name="selectedCourses" value="@course.CourseID">
@*For=""
this specifes which input element the label is assoicated with
in this case it is linked to the checkbox by the Course_CourseID
so for example course_12 is linked between the checkbox above and the label below using this label
so when a user clicks on the label, it will toggle the linked checkbox
*@
@*@course.Title
this is rendered first on the server side, and then on the view side it gets rendered as the course's title
so we receive the course title from the controller and render it here *@
<label class="form-check-label" for="@("course_" + course.CourseID)">
@course.Title
</label>
</div>
}
<button type="submit" class="btn btn-primary">Enroll</button>
Controllers > StudentsController.cs
public async Task<IActionResult> Create([Bind("ID,LastName,FirstMidName,EnrollmentDate,SelectedCourses,Courses")] Student student, int[] selectedCourses)
{
try
{
if (ModelState.IsValid)
{
// Add the student to the database
_context.Add(student);
await _context.SaveChangesAsync();
// If courses are selected, add the student to those courses
if (selectedCourses != null)
{
foreach (var courseId in selectedCourses)
{
var course = await _context.Courses.FindAsync(courseId);
if (course != null)
{
// Add the student to the course
course.Students.Add(student);
}
}
await _context.SaveChangesAsync();
}
return RedirectToAction(nameof(Index));
}
}
catch (DbUpdateException ex)
{
ModelState.AddModelError("", ex.Message);
}
catch (Exception)
{
ModelState.AddModelError("", "An error occurred. Please contact your system administrator.");
}
// If an error occurs or the model state is invalid, retrieve the list of available courses again
var availableCourses = await _context.Courses.ToListAsync();
ViewData["AvailableCourses"] = availableCourses;
return View(student);
}
Models > Student.cs
namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(50)]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; }
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}
public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<Course> Courses { get; set; }
[NotMapped] // Exclude from database mapping
public int[] SelectedCourses { get; set; }
}
}
Models > Course.cs
namespace ContosoUniversity.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; }
[StringLength(50, MinimumLength = 3)]
public string Title { get; set; }
[Range(0, 5)]
public int Credits { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
public ICollection<CourseAssignment> CourseAssignments { get; set; }
public ICollection<Student> Students { get; set; } // Navigation property for students
}
}
Thanks in advance.