Courses controller, model, view

Mudel

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace TallinnaRakenduslikKolledz.Models
{
    public class Course
    {
        [Key]
        
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }
        public Department? Department { get; set; }
        public int? DepartmentID { get; set; }
        public ICollection<Enrollment>? Enrollments { get; set; }
        public ICollection<CourseAssignment>? CourseAssignments { get; set; }
    }
}

See klass määrab õppeaine põhiandmed.
Õppeaine on seotud ühe osakonnaga ning vastav DepartmentID on välisvõti.
Lisaks on kursusel seosed üliõpilastega läbi Enrollments ning õpetajatega läbi CourseAssignments.

using System.ComponentModel.DataAnnotations;
using TallinnaRakenduslikKolledz.Models;

namespace TallinnaRakenduslikKolledz.Models
{
    public class CourseAssignment
    {
        [Key]
        public int ID { get; set; }
        public int InstructorID { get; set; }
        public int CourseID { get; set; }
        public Instructor Instructor { get; set; }
        public Course Course { get; set; }
    }
}

See on vahetabel, mida kasutatakse mitu-mitmele seose loomiseks õpetajate ja õppeainete vahel.
ID on unikaalne identifikaator igale seosekirjele.
InstructorID ja CourseID on välisvõtmed, mis viitavad vastavalt õpetajale ja kursusele.
Instructor ja Course omadused võimaldavad ligipääsu seotud objektidele Entity Frameworki kaudu.

Controller

using System.Formats.Asn1;
using System.Reflection.Metadata.Ecma335;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using TallinnaRakenduslikKolledz.Data;
using TallinnaRakenduslikKolledz.Models;

namespace TallinnaRakenduslikKolledz.Controllers
{
    public class CoursesController : Controller
    {
        private readonly SchoolContext _context;
        public CoursesController(SchoolContext context)
        {
            _context = context;
        }
        public IActionResult Index()
        {
            var courses = _context.Courses.Include(c => c.Department)
                .AsNoTracking();
            return View(courses);
        }
        // Create
        [HttpGet]
        public IActionResult Create()
        {
            ViewData["CreateEdit"] = "Create";
            PopulateDepartmentsDropDownList();
            return View();
        }
        [HttpPost, ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(Course course)
        {
            if (ModelState.IsValid)
            {
                _context.Courses.Add(course);
                await _context.SaveChangesAsync();
                PopulateDepartmentsDropDownList(course.DepartmentID);
            }
            return RedirectToAction("Index");
        }


        // Edit
        [HttpGet]
        public async Task<IActionResult> Edit(int? id)
        {
            ViewData["CreateEdit"] = "Edit";
            if (id == null || _context.Courses == null)
            {
                return NotFound();
            }
            var course = await _context.Courses
                .AsNoTracking()
                .FirstOrDefaultAsync(m => m.CourseID == id);
            if (course == null)
            {
                return NotFound();
            }
            PopulateDepartmentsDropDownList(course.DepartmentID);
            return View("Create", course);
        }

        [HttpPost, ActionName("Edit"), ValidateAntiForgeryToken]
        public async Task<IActionResult> EditConfirmed(int id, [Bind("CourseID,Title,Credits,DepartmentID, Enrollments, CourseAssignments")] Course course)
        {
            _context.Courses.Update(course);
            await _context.SaveChangesAsync();
            return RedirectToAction("Index");
        }

        // Delete
        [HttpGet]
        public async Task<IActionResult> Delete(int? id)
        {
            ViewData["DeleteDetails"] = "Delete";
            if (id == null || _context.Courses == null)
            {
                return NotFound();
            }
            var courses = await _context.Courses
                .Include(c => c.Department)
                .AsNoTracking()
                .FirstOrDefaultAsync(m => m.CourseID == id);
            if (courses == null)
            {
                return NotFound();
            }
            return View(courses);
        }
        [HttpPost, ActionName("Delete"), ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            if (_context.Courses == null)
            {
                return NotFound();
            }
            var course = await _context.Courses.FindAsync(id);
            if (course != null)
            {
                _context.Courses.Remove(course);
            }
            await _context.SaveChangesAsync();
            return RedirectToAction("Index");
        }

        //Details
        [HttpGet]
        public async Task<IActionResult> Details(int? id)
        {
            ViewData["DeleteDetails"] = "Details";
            if (id == null)
            {
                return NotFound();
            }
            var course = await _context.Courses.FirstOrDefaultAsync(c => c.CourseID == id);
            return View(nameof(Delete), course);
        }
        private void PopulateDepartmentsDropDownList(object selectedDepartment = null)
        {
            var departmentsQuery = from d in _context.Departments 
                                   orderby d.Name 
                                   select d;
            ViewBag.DepartmentID = new SelectList(departmentsQuery.AsNoTracking(), "DepartmentID", "Name", selectedDepartment);
        }

    }
}

CoursesController haldab kursustega seotud tegevusi MVC arhitektuuris ning suhtleb andmebaasiga läbi SchoolContext..

Index

Kuvab kõik kursused koos nende osakondadega.
Kasutab Include() osakonna andmete laadimiseks ja AsNoTracking() kiireks päringuks.

Create (GET)

Avab vaate uue kursuse lisamiseks ja täidab osakondade rippmenüü.

Create (POST)

Salvestab uue kursuse andmebaasi, kui mudel on korrektne (ModelState.IsValid).
Pärast salvestamist suunab tagasi Index vaatesse.

Edit (GET)

Leiab kursuse ID järgi ja avab sama vaate, mida kasutatakse ka loomiseks.
Kasutab FirstOrDefaultAsync() kursuse leidmiseks.

EditConfirmation (POST)

Uuendab kursuse andmed ja salvestab SaveChangesAsync() abil.

Delete (GET)

Kuvab kustutamise kinnituse vaate koos osakonna infoga.
Kasutab Include() ja FirstOrDefaultAsync().

DeleteConfirmed (POST)

Leiab kursuse FindAsync() abil ja kustutab selle.
Salvestab muudatused andmebaasi.

Details

Kuvab kursuse detailid, kasutades FirstOrDefaultAsync().

PopulateDepartmentsDropDownList

Täidab rippmenüü osakondade nimekirjaga.
Kasutab LINQ päringut from … select ja AsNoTracking().

Vaated

Index

@model IEnumerable<TallinnaRakenduslikKolledz.Models.Course>
@{
	ViewData["Title"] = "Kursused/Õppeained";
}
<h2>Kursused</h2>
<p>
	<a asp-action="Create">Tee uus kursus</a>
</p>

<table class="table">

	<thead>
		<tr>
			<th> @Html.DisplayNameFor(Model => Model.CourseID)</th>
			<th> @Html.DisplayNameFor(Model => Model.Title)</th>
			<th> @Html.DisplayNameFor(Model => Model.Credits)</th>
			<th> @Html.DisplayNameFor(Model => Model.Department.Name)</th>
			<th> @Html.DisplayNameFor(Model => Model.Department.Administrator.FullName)</th>
			<th> @Html.DisplayNameFor(Model => Model.Enrollments)</th>
			<th> @Html.DisplayNameFor(Model => Model.CourseAssignments)</th>
			<th>Tööriistad</th>
		</tr>
	</thead>

	<tbody>
		@foreach (var course in Model)
		{
			<tr>
				<td>
						@Html.DisplayFor(modelItem => course.CourseID)
				</td>
				<td>
						@Html.DisplayFor(modelItem => course.Title)
				</td>
				<td>
						@Html.DisplayFor(modelItem => course.Credits)
				</td>
				<td>
						@Html.DisplayFor(modelItem => course.Department.Name)
				</td>
				<td>
						@Html.DisplayFor(modelItem => course.Department.Administrator.FullName)
				</td>
				<td>
					@Html.DisplayFor(modelItem => course.Enrollments)
				</td>
				<td>
					@Html.DisplayFor(modelItem => course.CourseAssignments)
				</td>
				<td>
					<a asp-action="Edit" asp-route-id="@course.CourseID">Muuda</a>
					<a asp-action="Details" asp-route-id="@course.CourseID">Vaata</a>
					<a asp-action="Delete" asp-route-id="@course.CourseID">Kustuta</a>
				</td>
			</tr>
			
		}
	</tbody>

</table>

Create/Edit

@model TallinnaRakenduslikKolledz.Models.Course
@{
	ViewData["Title"] = "Uus kursus";
}
@if (ViewBag.CreateEdit == "Create")
{
	<h1>Tee uus kursus</h1>
	<h4>Sisesta info</h4>
	<hr/>
	<div class="row">
		<div class="col-md-4">
			<form asp-action="Create">
				<div asp-validation-summary="ModelOnly" class="text-danger"></div>
				@*
				<div>
					<label asp-for="CourseID" class="control-label"></label>
					<input asp-for="CourseID" class="form-control" />
					<span asp-validation-for="CourseID" class="text-danger"></span>
				</div>
				*@
				<div>
					<label asp-for="Title" class="control-label"></label>
					<input asp-for="Title" class="form-control"></input>a
					<span asp-validation-for="Title" class="text-danger"></span>
				</div>
				<div>
					<label asp-for="Credits" class="control-label"></label>
					<input asp-for="Credits" class="form-control"></input>
					<span asp-validation-for="Credits" class="text-danger"></span>
				</div>
				<div>
					<label asp-for="Department" class="control-label"></label>
					<select asp-for="DepartmentID" class="form-control asp-items="ViewBag.DepartmentID">
						<option value="" class="form-control" >--Vali osakond--</option>
					</select>
					<span asp-validation-for="DepartmentID" class="text-danger"></span>
				</div>
				<div>
					<label asp-for="Enrollments" class="control-label"></label>
					<input asp-for="Enrollments" class="form-control"></input>
					<span asp-validation-for="Enrollments" class="text-danger"></span>
				</div>
				<div>
					<label asp-for="CourseAssignments" class="control-label"></label>
					<input asp-for="CourseAssignments" class="form-control"></input>
					<span asp-validation-for="CourseAssignments" class="text-danger"></span>
				</div>
				<div class="form-group">
					<input type="submit" value="Tee uus" class="btn btn-primary"/> | <a asp-action="Index" class="btn btn-outline-primary">Tühista</a>
				</div>
			</form>
		</div>
	</div>
}

@if (ViewBag.CreateEdit == "Edit")
{
	<h1>Muuda kursust</h1>
	<h4>Sisesta info</h4>
	<form asp-action="Edit">
		<input type="hidden" asp-for="CourseID" />

		<div asp-validation-summary="ModelOnly" class="text-danger"></div>

		<div class="form-group">
			<label asp-for="Title" class="control-label"></label>
			<input asp-for="Title" class="form-control" />
			<span asp-validation-for="Title" class="text-danger"></span>
		</div>

		<div class="form-group">
			<label asp-for="Credits" class="control-label"></label>
			<input asp-for="Credits" class="form-control" />
			<span asp-validation-for="Credits" class="text-danger"></span>
		</div>
		<div>
			<label asp-for="Department" class="control-label"></label>
			<select asp-for="DepartmentID" class="form-control asp-items="ViewBag.DepartmentID">
				<option value="" class="form-control">--Vali osakond--</option>
			</select>
			<span asp-validation-for="DepartmentID" class="text-danger"></span>
		</div>
		<div class="form-group">
			<label asp-for="Enrollments" class="control-label"></label>
			<input asp-for="Enrollments" class="form-control" />
			<span asp-validation-for="Enrollments" class="text-danger"></span>
		</div>
		<div class="form-group">
			<label asp-for="CourseAssignments" class="control-label"></label>
			<input asp-for="CourseAssignments" class="form-control" />
			<span asp-validation-for="CourseAssignments" class="text-danger"></span>
		</div>

		<div class="form-group">
			<input type="submit" value="Muuda" class="btn btn-primary" /> | <a asp-action="Index" class="btn btn-outline-primary">Mine tagasi loendisse </a>
		</div>
	</form>
}


Delete/Details

@model TallinnaRakenduslikKolledz.Models.Course
@{
	ViewData["Title"] = "Vaata rohkem";
}
<!-- Details -->
@if (ViewBag.DeleteDetails == "Details")
{
	<p>
		<h3>Osakonna andmed</h3>
	</p>
}
<!-- Delete -->
@if (ViewBag.DeleteDetails == "Delete")
{
	<p>
		<h3>Kustuta osakond</h3>
	</p>
}

<h2>@Html.DisplayFor(modelItem => Model.Title)</h2>
<div>
	<dl class="row">
		<dt class="col-sm-2">@Html.DisplayNameFor(Model => Model.CourseID)</dt>
		<dt class="col-sm-2">@Html.DisplayFor(Model => Model.CourseID)</dt>
		<dt class="col-sm-2">@Html.DisplayNameFor(Model => Model.Title)</dt>
		<dt class="col-sm-2">@Html.DisplayFor(Model => Model.Title)</dt>
		<dt class="col-sm-2">@Html.DisplayNameFor(Model => Model.Credits)</dt>
		<dt class="col-sm-2">@Html.DisplayFor(Model => Model.Credits)</dt>
		<dt class="col-sm-2">@Html.DisplayNameFor(Model => Model.Department)</dt>
		<dt class="col-sm-2">@Html.DisplayFor(Model => Model.Department)</dt>
		<dt class="col-sm-2">@Html.DisplayNameFor(Model => Model.Enrollments)</dt>
		<dt class="col-sm-2">@Html.DisplayFor(Model => Model.Enrollments)</dt>
		<dt class="col-sm-2">@Html.DisplayNameFor(Model => Model.CourseAssignments)</dt>
		<dt class="col-sm-2">@Html.DisplayFor(Model => Model.CourseAssignments)</dt>
	</dl>
	@if (ViewBag.DeleteDetails == "Delete")
	{
		<form asp-action="Delete">
			<input type="hidden" asp-for="CourseID" />
			<input type="submit" value="Kustuta" class="btn btn-danger" />
		</form>
	}
	<a asp-action="Index">Tühista</a>
</div>