Skip to main content

ASP.NET Core MVC Fundamentals

Level: Intermediate

ℹ️ What You'll Learn
  • MVC pattern: Model (data objects), View (HTML templates), Controller (request handlers)
  • Request flow: Browser → Controller action → gets Model data → passes to View → View renders HTML
  • Controller: Class handling HTTP requests (StudentsController, TeachersController)
  • Controller base class: public class StudentsController : Controller (includes View(), RedirectToAction(), etc.)
  • Action methods: public IActionResult Index() handles HTTP request, returns HTML response
  • View (.cshtml): HTML template mixing C# and HTML (@model List<Student>, @foreach (var s in Model))
  • Model: Data passed from Controller to View (return View(students) passes student list)
  • Model binding: Form data automatically converts to model (Create(Student student) populated from POST form)
  • Tag helpers: <input asp-for="Name"> generates form fields bound to model properties
  • Routing: URL maps to Controller action (/students/details/5 → StudentsController.Details(id: 5))
  • ViewData/ViewBag: Flexible data passing Controller → View (ViewData["Title"] = "Students")
  • School Management pages: StudentList (Index), StudentDetails, CreateStudent, EditStudent
  • HTML form submission: POST to action, action validates, returns View with errors or redirects to success page
  • CRUD workflow: Index (list) → Create (form) → POST Create (save) → Redirect → Details (view)

What is MVC?

Model-View-Controller architectural pattern.

  • Model = Data (Student, Exam, Fee)
  • View = HTML UI (Razor .cshtml files)
  • Controller = Request handler, business logic
User Request → Controller → Model → View → HTML Response

Project Structure

SMS.Web/
├── Controllers/
│ ├── StudentsController.cs
│ ├── ExamsController.cs
│ └── FeesController.cs
├── Views/
│ ├── Students/
│ │ ├── Index.cshtml
│ │ ├── Details.cshtml
│ │ ├── Create.cshtml
│ │ └── Edit.cshtml
│ ├── Shared/
│ │ ├── _Layout.cshtml
│ │ └── _ValidationScriptsPartial.cshtml
│ └── Home/
│ └── Index.cshtml
├── Models/
│ ├── Student.cs
│ ├── Exam.cs
│ └── ViewModels/
│ └── StudentViewModel.cs
├── Program.cs
└── appsettings.json

Controllers and Actions

Controller = class handling HTTP requests. Action = public method returning view or data.

using Microsoft.AspNetCore.Mvc;

public class StudentsController : Controller
{
private readonly IStudentService _service;

public StudentsController(IStudentService service)
{
_service = service;
}

// GET: /students
public async Task<IActionResult> Index()
{
var students = await _service.GetStudentsAsync();
return View(students);
}

// GET: /students/5
public async Task<IActionResult> Details(int id)
{
var student = await _service.GetStudentAsync(id);
if (student == null)
return NotFound();

return View(student);
}

// GET: /students/create
public IActionResult Create()
{
return View();
}

// POST: /students/create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Student student)
{
if (ModelState.IsValid)
{
await _service.CreateStudentAsync(student);
return RedirectToAction(nameof(Details), new { id = student.Id });
}

return View(student);
}

// GET: /students/edit/5
public async Task<IActionResult> Edit(int id)
{
var student = await _service.GetStudentAsync(id);
if (student == null)
return NotFound();

return View(student);
}

// POST: /students/edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, Student student)
{
if (id != student.Id)
return NotFound();

if (ModelState.IsValid)
{
await _service.UpdateStudentAsync(id, student);
return RedirectToAction(nameof(Index));
}

return View(student);
}

// POST: /students/delete/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Delete(int id)
{
await _service.DeleteStudentAsync(id);
return RedirectToAction(nameof(Index));
}
}

Views and Razor Syntax

View = Razor .cshtml file. Mix C# and HTML.

File: Views/Students/Index.cshtml

@model List<Student>

@{
ViewData["Title"] = "Students";
}

<h1>Students List</h1>

<a class="btn btn-primary" asp-action="Create">Add Student</a>

<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Roll Number</th>
<th>Class</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (var student in Model)
{
<tr>
<td>@student.Name</td>
<td>@student.RollNumber</td>
<td>@student.ClassName</td>
<td>@student.Status</td>
<td>
<a asp-action="Details" asp-route-id="@student.Id">View</a>
<a asp-action="Edit" asp-route-id="@student.Id">Edit</a>
<form asp-action="Delete" asp-route-id="@student.Id" method="post" style="display:inline;">
<button type="submit" onclick="return confirm('Are you sure?');">Delete</button>
</form>
</td>
</tr>
}
</tbody>
</table>

Model Binding from Forms

Forms automatically bind to model properties.

File: Views/Students/Create.cshtml

@model Student

@{
ViewData["Title"] = "Create Student";
}

<h1>Add New Student</h1>

<form asp-action="Create" method="post">
<div class="form-group">
<label asp-for="Name"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>

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

<div class="form-group">
<label asp-for="ClassName"></label>
<select asp-for="ClassName" class="form-control">
<option value="">Select Class</option>
<option value="10-A">10-A</option>
<option value="10-B">10-B</option>
<option value="11-A">11-A</option>
</select>
<span asp-validation-for="ClassName" class="text-danger"></span>
</div>

<div class="form-group">
<label asp-for="Status"></label>
<select asp-for="Status" class="form-control">
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div>

<button type="submit" class="btn btn-primary">Create</button>
<a asp-action="Index" class="btn btn-secondary">Cancel</a>
</form>

@section Scripts {
@{
await Html.RenderPartialAsync("_ValidationScriptsPartial");
}
}

POST binds form values to Student model automatically.

Tag Helpers

Replace HTML with smart tags. Generate correct URLs automatically.

Tag HelperPurpose
asp-actionAction method name
asp-controllerController name
asp-route-idRoute parameter value
asp-forProperty binding (label, input)
asp-validation-forValidation error message

Layout and Shared Views

File: Views/Shared/_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewData["Title"] - SMS</title>
<link rel="stylesheet" href="~/lib/bootstrap/css/bootstrap.min.css" />
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-controller="Home" asp-action="Index">SMS</a>
<button class="navbar-toggler" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Students" asp-action="Index">Students</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Exams" asp-action="Index">Exams</a>
</li>
</ul>
</div>
</div>
</nav>

<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>

<script src="~/lib/jquery/jquery.min.js"></script>
<script src="~/lib/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>

In other views: @{ Layout = "_Layout"; }

Program.cs Setup

var builder = WebApplicationBuilder.CreateBuilder(args);

// Add MVC
builder.Services.AddControllersWithViews();

// Services
builder.Services.AddScoped<IStudentService, StudentService>();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();
app.UseRouting();

app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"
);

app.Run();

Routing

Default route: {controller}/{action}/{id?}

Examples:

  • /students → StudentsController.Index()
  • /students/details/5 → StudentsController.Details(id=5)
  • /students/edit/5 → StudentsController.Edit(id=5)

Key Takeaways

  • MVC = separate concerns (Model, View, Controller)
  • Controllers = handle requests and orchestrate
  • Views = Razor templates with C# expressions
  • Model binding = automatic form-to-object conversion
  • Tag helpers = generate proper HTML and URLs
  • Layout = shared header, nav, footer
💡 MVC Tip

Keep business logic in services, not controllers. Controllers orchestrate only.

🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on ASP.NET Core MVC Fundamentals. Try these prompts:

  • "What's the difference between MVC and Web API?"
  • "How does model binding work?"
  • "What are tag helpers?"
  • "When should I use partials vs layouts?"
  • "Quiz me on ASP.NET Core MVC"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

nexcoding.in