Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active December 9, 2025 10:21
Show Gist options
  • Select an option

  • Save sunmeat/539df762c776297a7bf92ff26da03e83 to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/539df762c776297a7bf92ff26da03e83 to your computer and use it in GitHub Desktop.
default CRUD-controller ASP.NET Core example
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace mvc.Controllers
{
public class StudentController : Controller // контролер для CRUD-операцій над студентами
{
private readonly StudentContext _context; // контекст бази даних
public StudentController(StudentContext context) // конструктор з ін'єкцією залежностей
{
_context = context;
}
// GET: Student
public async Task<IActionResult> Index() // дія для відображення списку всіх студентів
{
return View(await _context.Students.ToListAsync()); // передає асинхронно отриманий список у подання, це модель даних
// !!! перейти у файл Views / Student / Index.cshtml, подивитися як там отримується модель (32 рядок)
// коментарі по всьому цьому файлу, включно з тег-хелперами ASP.NET Core
}
// GET: Student/Details/5
public async Task<IActionResult> Details(int? id) // дія для перегляду деталей студента по айді
{
if (id == null) return NotFound(); // повертає помилку 404, якщо id відсутній
var student = await _context.Students // асинхронно шукає студента за id
.FirstOrDefaultAsync(m => m.Id == id); // отримує перший збіг або null
if (student == null) return NotFound(); // повертає 404, якщо студент не існує
return View(student); // передає знайденого студента у подання
}
// GET: Student/Create
public IActionResult Create() // відображає форму створення нового студента
{
return View(); // повертає порожнє подання Create
}
// POST: Student/Create
[HttpPost] // позначає метод як обробник POST-запиту
[ValidateAntiForgeryToken] // перевіряє анти-підробний токен, щоб захиститися від CSRF атак https://corewin.ua/blog/cross-site-request-forgery-csrf/
public async Task<IActionResult> Create([Bind("Id,Name,Surname,Age,GPA")] Student student) // приймає модель зі вказаними полями
{
if (ModelState.IsValid) // перевіряє валідність даних за анотаціями моделі
{
_context.Add(student); // додає нового студента до контексту
await _context.SaveChangesAsync(); // асинхронно зберігає зміни в БД
return RedirectToAction(nameof(Index)); // перенаправляє на список студентів
}
return View(student); // якщо дані невалідні — повертає форму з помилками
}
// GET: Student/Edit/5
public async Task<IActionResult> Edit(int? id) // відображає форму редагування
{
if (id == null) return NotFound(); // повертає 404
var student = await _context.Students.FindAsync(id); // шукає студента за первинним ключем
if (student == null) return NotFound(); // повертає 404, якщо не знайдено
return View(student); // передає студента у форму редагування
}
// POST: Student/Edit/5
[HttpPost] // обробляє POST-запит на оновлення
[ValidateAntiForgeryToken] // захист від CSRF
public async Task<IActionResult> Edit(int id, [Bind("Id,Name,Surname,Age,GPA")] Student student) // приймає id та оновлені дані
{
if (id != student.Id) return NotFound(); // перевіряє, чи співпадає id з маршруту та моделі, якщо ні — 404
if (ModelState.IsValid) // перевіряє валідність введених даних
{
try
{
_context.Update(student); // позначає об'єкт як змінений
await _context.SaveChangesAsync(); // зберігає зміни в БД
}
catch (DbUpdateConcurrencyException) // ловить помилку конкурентного оновлення, якщо хтось інший змінив або видалив запис
{
if (!StudentExists(student.Id)) return NotFound(); // перевіряє, чи студент ще існує
else throw; // інакше пробрасує виняток далі
}
return RedirectToAction(nameof(Index)); // після успіху — назад до списку
}
return View(student); // якщо дані невалідні — повертає форму з помилками
}
// GET: Student/Delete/5
public async Task<IActionResult> Delete(int? id) // відображає сторінку підтвердження видалення
{
if (id == null) return NotFound();
var student = await _context.Students.FirstOrDefaultAsync(m => m.Id == id);
if (student == null) return NotFound();
return View(student); // показує сторінку підтвердження з даними студента
}
// POST: Student/Delete/5
[HttpPost, ActionName("Delete")] // ім'я дії для маршруту — Delete, треба вказати щоб не було конфлікту з GET-дією, т.як не можна створити два методи з однаковим ім'ям та сигнатурою
[ValidateAntiForgeryToken] // захист від CSRF
public async Task<IActionResult> DeleteConfirmed(int id) // підтверджує видалення
{
var student = await _context.Students.FindAsync(id); // шукає студента
if (student != null) // якщо знайдено
{
_context.Students.Remove(student); // видаляє з контексту
}
await _context.SaveChangesAsync(); // зберігає видалення в БД
return RedirectToAction(nameof(Index)); // перенаправляє на список
}
private bool StudentExists(int id) // перевіряє існування студента за id
{
return _context.Students.Any(e => e.Id == id); // повертає true, якщо є хоча б один збіг
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment