MVC — Controllers, Actions and Views
As ReadingRoom grows, Program.cs fills with dozens of lambdas. MVC offers a different shape: one class per resource, one method per endpoint, with routing, validation and filters declared by attributes. Many existing .NET codebases are built this way, so you will read it constantly.
The rule
Controller groups the actions; attributes route them; the action returns the result.
MVC stands for Model (the data), View (the HTML shown to a person) and Controller (the class that handles requests). For an API there are no views, so a controller derives from ControllerBase:
[ApiController]
[Route("books")]
public class BooksController(BookStore store) : ControllerBase
{
[HttpGet("{id:int}")]
public ActionResult<Book> GetById(int id)
{
var book = store.Find(id);
if (book is null) return NotFound();
return book;
}
[HttpPost]
public ActionResult<Book> Create(Book book)
{
store.Add(book);
return CreatedAtAction(nameof(GetById), new { id = book.Id }, book);
}
}Program.cs just switches controllers on:
builder.Services.AddControllers();
// ...
app.MapControllers();Each public method is an action. [Route] on the class sets the prefix; [HttpGet("{id:int}")] adds the method and the rest of the path. [ApiController] switches on API behaviour: if the incoming model fails validation, it answers 400 with problem details before your action runs, and it infers that complex parameters come from the body.
For web pages, derive from Controller instead and return View(book); — the framework finds Views/Books/GetById.cshtml and renders it with the book as its model.
The shortcut
To find which action answers a URL, join the class route and the method route, then match the HTTP method.
Class route
[Route("books")]onBooksControllergives the prefixbooks.
The trap: forgetting app.MapControllers(). The controllers compile fine, but no URL reaches them, so every request is a 404.
Drills
Answer fast — trust the rule.
Which base class should an API-only controller derive from?
A POST sends a book with a missing [Required] title to an [ApiController]. What happens?
Controllers are written but every request returns 404. What is most likely missing?
In MVC, which part is the HTML shown to a person?
Remember
- Controller groups the actions; attributes route them; the action returns the result.
- Join the class route and method route to find the action.
ControllerBasefor APIs,Controllerfor views;MapControllers()or nothing is reached.
