Post

Building a Course Management Application with ASP.NET Core

Are you looking to streamline your course management process? With ASP.NET Core, you can create a robust web application to manage courses and student enrollments efficiently. In this tutorial, we’ll walk through the steps to build a course management application from scratch.

Setting Up the Project

To begin, create a new ASP.NET Core project and configure the database connection in the appsettings.json file. Here’s how you can set up your appsettings.json:

1
2
3
4
5
"ConnectionStrings": {
  "CourseDb": "Server=tcp:127.0.0.1,1433;Database=CourseDB;
               User Id=userid;Password=pass@;Integrated security=False;
               MultipleActiveResultSets=true;TrustServerCertificate=true"
}

Defining Entities

Next, define the entities for courses and students in the Entities folder:

Course.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Define the Course entity
public class Course
{
    public int CourseId { get; set; }

    [Required(ErrorMessage = " Name is required")]
    public string CourseName { get; set; }

    [Required(ErrorMessage = " Instructor is required")]
    public string? Instructor { get; set; }

    [Required(ErrorMessage = " Start date is required")]
    public DateTime? StartDate { get; set; }

    [Required(ErrorMessage = " Room number is required")]
    [RegularExpression(@"^[0-9][A-Z][0-9]{2}$", 
     ErrorMessage = "Input must be in the format")]
    public string? RoomNumber { get; set; }

    public ICollection<Student>? Students { get; set; }
}

Student.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// Define the Student entity
public enum ConfirmStatus
{
    ConfirmationMessageNotSent,
    ConfirmationMessageSent,
    EnrollmentConfirmed,
    EnrollmentDeclined
}

public class Student
{
    public int StudentId { get; set; }

    [Required(ErrorMessage = " Student name is required")]
    public string? Name { get; set; }

    [Required(ErrorMessage = " Email is required")]
    [EmailAddress(ErrorMessage = "Invalid email address")]
    public string? Email { get; set; }

    public ConfirmStatus Status { get; set; }

    public int? CourseId { get; set; }
    public Course? Course { get; set; }

    public string TransformedStatus
    {
        get
        {
            switch (Status)
            {
                case ConfirmStatus.ConfirmationMessageNotSent:
                    return "Confirmation Message Not Sent";
                case ConfirmStatus.ConfirmationMessageSent:
                    return "Confirmation Message Sent";
                case ConfirmStatus.EnrollmentConfirmed:
                    return "Enrollment Confirmed";
                case ConfirmStatus.EnrollmentDeclined:
                    return "Enrollment Declined";
                default:
                    return "Unknown Status";
            }
        }
    }
}

Creating the DbContext

With the entities in place, create a DbContext class to represent the database context. Configure the one-to-many relationship between courses and students using Fluent API in the OnModelCreating method. Here’s how you can set up your CourseDbContext.cs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Define the DbContext
public class CourseDbContext : DbContext
{
    public CourseDbContext(DbContextOptions<CourseDbContext> dbContextOptions) : base(dbContextOptions)
    {
    }

    public DbSet<Course> Courses { get; set; }
    public DbSet<Student> Students { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Course>()
            .HasMany<Student>(c => c.Students)
            .WithOne(s => s.Course)
            .HasForeignKey(s => s.CourseId)
            .IsRequired(false);
    }
}

Seeding Data

Seed some initial data into the database to test our application. This step is crucial for populating the database with sample courses and student enrollments. Here’s how you can seed data into your database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
modelBuilder.Entity<Course>().HasData(
    new Course()
    {
        CourseId = 1,
        CourseName = "Programming Microsoft Web Technologies",
        Instructor = "Manny Singh",
        StartDate = new DateTime(2024, 1, 18, 2, 26, 31),
        RoomNumber = "1C09",
    },
    new Course()
    {
        CourseId = 2,
        CourseName = "Distributed Application Development",
        Instructor = "Manny Singh",
        StartDate = new DateTime(2024, 12, 19, 2, 26, 31),
        RoomNumber = "1C09",
    }
);

modelBuilder.Entity<Student>().HasData(
    new Student()
    {
        StudentId = 1,
        Name = "Gunsu Lee",
        Email = "glee6937@conestogac.on.ca",
        Status = ConfirmStatus.ConfirmationMessageNotSent,
        CourseId = 1,
    },
    new Student()
    {
        StudentId = 2,
        Name = "Lee Gunsu",
        Email = "glee6937@conestogac.on.ca",
        Status = ConfirmStatus.ConfirmationMessageNotSent,
        CourseId = 2,
    }
);

Implementing Controllers

Now that we have our entities and database context set up, it’s time to create controllers to handle various actions in our application. We’ll create a CourseController to manage courses and student enrollments. Here’s how you can set up your controller:

CourseController.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
namespace CourseManager.Controllers
{
    public class CourseController : Controller
    {
        private CourseDbContext _courseDbContext; // CourseDbContext
        private EmailService _emailService; // to send an email

        public CourseController(CourseDbContext courseDbContext, EmailService emailService)
        {
            _courseDbContext = courseDbContext;
            _emailService = emailService;
        }

        // Action to list all courses
        [HttpGet("/courses")]
        public IActionResult GetAllCourses()
        {
            var courses = _courseDbContext.Courses
                .OrderByDescending(a => a.StartDate)
                .ToList();

            var studentCount = _courseDbContext.Courses
                .Include(c => c.Students)
                .ToDictionary(c => c.CourseId, c => c.Students.Count);

            CourseListViewModel courseListViewModel = new CourseListViewModel()
            {
                Courses = courses,
                StudentCounts = studentCount
            };

            return View("Lists", courseListViewModel);
        }

        // Add more actions as needed for managing courses
    }
}

Building Views

With our controllers in place, let’s design views to display course information and provide user interaction. We’ll create a view to list all courses and another view to manage individual courses.

Lists.cshtml (View to list all courses)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@model CourseListViewModel
@{
    ViewData["Title"] = "All courses";
}

<a asp-controller="Course" asp-action="GetAddCourseRequest">Add new course</a>
<table class="table table-bordered table-striped">
    <thead>
        <tr>
            <th>Name</th>
            <!-- Add more table headers as needed -->
        </tr>
    </thead>
    <tbody>
        @foreach (Course cs in Model.Courses)
        {
            <tr>
                <td>@cs.CourseName</td>
                <!-- Add more table data cells as needed -->
                <td><a asp-controller="Course" asp-action="GetManageCourseRequestById" asp-route-id="@cs.CourseId">Manage</a></td>
            </tr>
        }
    </tbody>
</table>

Running the Application

Now that everything is set up, build and run your ASP.NET Core application. You can navigate to the appropriate URLs to access the course management functionality, such as viewing all courses and managing individual courses.

I’ll cover additional features and enhancements for our course management application in the next post!

This post is licensed under CC BY 4.0 by the author.