Introduction
Model-View-Controller (MVC) is the architectural pattern at the heart of most ASP.NET Core web applications you will build in Indian IT — from internal HR portals at Infosys to customer-facing storefronts at product startups. If you understand MVC deeply, every later topic (routing, EF Core, Identity, Web API) clicks into place.
In this lesson we explain MVC with plain-English analogies, trace the full request lifecycle from browser URL to HTML response, build a working online bookstore on ShopNest (list books + view details), and compare MVC with Web API, Razor Pages, and Blazor so you pick the right tool in interviews and on the job.
After this article you will
- Explain Model, View, and Controller roles without memorizing definitions
- Trace an HTTP request through the ASP.NET Core pipeline step by step
- Build Book list and Book details pages with MVC
- Compare MVC vs Web API vs Razor Pages vs Blazor
- Answer common MVC fresher interview questions
Prerequisites
- Article 3 — Project structure
- ShopNest solution with MVC project (
dotnet new mvc -n ShopNest.Web) - Basic C#: classes, lists, properties
MVC pattern explained
Level 1 — Bookstore analogy
Imagine a physical bookstore:
- Model — the inventory database: title, author, price, stock count. Pure data and business rules ("don't sell out-of-stock books").
- View — the shelf display and price tags customers see. HTML pages styled with CSS.
- Controller — the shop assistant. Customer asks "Show me sci-fi books" → assistant fetches from inventory (Model) → arranges display (View).
The customer never walks into the warehouse (Model directly). The assistant (Controller) mediates. That separation keeps UI changes independent from database logic — critical when your team has separate frontend and backend developers.
Level 2 — Technical roles in ASP.NET Core
| Part | What it is | ShopNest bookstore example |
|---|---|---|
| Model | Data + validation + business logic | Book class, BookService |
| View | UI template (Razor .cshtml) | Views/Books/Index.cshtml |
| Controller | Handles HTTP, orchestrates Model → View | BooksController |
Level 3 — Request lifecycle (step by step)
1. User clicks link: /Books/Details/5
2. Browser sends HTTP GET to Kestrel
3. Middleware runs (HTTPS, static files, routing, auth…)
4. Routing matches: controller=Books, action=Details, id=5
5. BooksController.Details(5) executes
6. Controller asks BookService for book id=5 (Model layer)
7. Controller passes Book object to View via return View(book)
8. Razor engine renders Views/Books/Details.cshtml → HTML
9. HTML travels back through middleware → browser displays page
[Browser] --GET /Books/Details/5--> [Kestrel]
--> [Middleware Pipeline]
--> [BooksController.Details]
--> [IBookService / DbContext]
--> [Book entity]
--> [Details.cshtml Razor View]
--> [HTML Response] --> [Browser]
Common misconceptions
❌ MYTH: Model means only the database entity.
✅ TRUTH: In MVC, "Model" means all data passed to the View — often a ViewModel, not raw EF entities.
❌ MYTH: One controller per database table always.
✅ TRUTH: Controllers align with user features (Books, Cart, Checkout), not always 1:1 with tables.
❌ MYTH: MVC is outdated because of SPAs.
✅ TRUTH: MVC remains ideal for SEO-heavy sites, admin panels, and server-rendered apps — common in Indian enterprise projects.
Hands-on: ShopNest online bookstore
Step 1 — Book model
// File: Models/Book.cs
namespace ShopNest.Web.Models;
public class Book
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Author { get; set; } = string.Empty;
public decimal Price { get; set; }
public string CoverImageUrl { get; set; } = string.Empty;
public string Summary { get; set; } = string.Empty;
}
Step 2 — Book service (thin data access for now)
// File: Services/IBookService.cs
public interface IBookService
{
IReadOnlyList<Book> GetAll();
Book? GetById(int id);
}
// File: Services/BookService.cs
public class BookService : IBookService
{
private static readonly List<Book> _books =
[
new() { Id = 1, Title = "Clean Code", Author = "Robert C. Martin", Price = 499,
Summary = "Essential practices for professional software craftsmanship." },
new() { Id = 2, Title = "ASP.NET Core in Action", Author = "Andrew Lock", Price = 899,
Summary = "Deep dive into modern ASP.NET Core development." },
new() { Id = 3, Title = "C# in Depth", Author = "Jon Skeet", Price = 750,
Summary = "Advanced C# for serious .NET developers." }
];
public IReadOnlyList<Book> GetAll() => _books;
public Book? GetById(int id) => _books.FirstOrDefault(b => b.Id == id);
}
Step 3 — Register service in Program.cs
builder.Services.AddControllersWithViews();
builder.Services.AddSingleton<IBookService, BookService>();
Step 4 — BooksController
// File: Controllers/BooksController.cs
using Microsoft.AspNetCore.Mvc;
using ShopNest.Web.Models;
using ShopNest.Web.Services;
public class BooksController : Controller
{
private readonly IBookService _books;
public BooksController(IBookService books) => _books = books;
// GET /Books or /Books/Index
public IActionResult Index()
{
var list = _books.GetAll();
return View(list);
}
// GET /Books/Details/5
public IActionResult Details(int id)
{
var book = _books.GetById(id);
if (book is null) return NotFound();
return View(book);
}
}
Step 5 — List view (Index)
@* File: Views/Books/Index.cshtml *@
@model IReadOnlyList<ShopNest.Web.Models.Book>
@{
ViewData["Title"] = "Bookstore";
}
<h1>ShopNest Bookstore</h1>
<div class="row">
@foreach (var book in Model)
{
<div class="col-md-4 mb-4">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">@book.Title</h5>
<p class="card-text text-muted">@book.Author</p>
<p class="fw-bold">₹@book.Price</p>
<a asp-action="Details" asp-route-id="@book.Id" class="btn btn-primary btn-sm">View details</a>
</div>
</div>
</div>
}
</div>
Step 6 — Details view
@* File: Views/Books/Details.cshtml *@
@model ShopNest.Web.Models.Book
@{
ViewData["Title"] = Model.Title;
}
<h1>@Model.Title</h1>
<p class="lead">by @Model.Author</p>
<p>@Model.Summary</p>
<p class="fs-4 fw-bold">₹@Model.Price</p>
<a asp-action="Index" class="btn btn-outline-secondary">← Back to list</a>
Step 7 — Run and test
dotnet run --project ShopNest.Web
# Browse: https://localhost:7xxx/Books
# Click "View details" on any book → /Books/Details/1
Expected: grid of three books; details page shows title, author, summary, price in ₹.
MVC vs Web API vs Razor Pages vs Blazor
| Pattern | Best for | Output | ShopNest use case |
|---|---|---|---|
| MVC | Server-rendered sites, SEO, complex UI flows | HTML | Public bookstore, marketing pages |
| Web API | Mobile/SPA backends, microservices | JSON | ShopNest.API for Android/iOS cart |
| Razor Pages | Page-focused apps, less ceremony than MVC | HTML | Simple admin CRUD screens |
| Blazor | .NET-only teams, rich client interactivity | HTML + WebAssembly/SignalR | Internal dashboards (Article 71) |
Interview tip: MVC and Razor Pages share routing and Razor syntax; MVC adds explicit Controllers folder. Web API typically has no Views. Blazor runs C# in the browser (WASM) or on server via SignalR.
Common errors
🔴 InvalidOperationException: View 'Index' not found
View must live at Views/Books/Index.cshtml matching controller name.
🔴 404 on /Books/Details
Missing route id or action name typo — use Tag Helpers asp-action / asp-route-id.
🔴 Fat controller with SQL inside
Move data access to services; EF Core comes in Article 13+.
Interview questions (MVC — fresher focus)
Q1: What is MVC?
A: Separation of concerns — Model (data/logic), View (UI), Controller (request handler orchestrating both).
Q2: What is IActionResult?
A: Return type for controller actions — View(), Json(), Redirect(), NotFound(), etc.
Q3: Difference between ViewData and ViewBag?
A: Both pass weakly-typed data to views; ViewBag is dynamic wrapper over ViewData dictionary.
Q4: What is routing?
A: Maps URL to controller action — conventional {controller}/{action}/{id} or attribute routes (Article 6).
Q5: Why dependency injection in controllers?
A: Testability, loose coupling — pass IBookService via constructor instead of new BookService().
Q6: MVC vs Web API?
A: MVC returns views for browsers; API returns data (JSON) for programmatic clients.
Q7: What is Razor?
A: Syntax mixing HTML with C# (@) compiled to C# classes for fast rendering.
Q8: Where does business logic go?
A: Services / domain layer — not in Views; minimally in Controllers; never in Views.
Summary
- MVC separates data (Model), UI (View), and request handling (Controller)
- Request flows: URL → routing → controller → model/service → Razor view → HTML
- ShopNest bookstore: BooksController with Index + Details actions
- Choose MVC for SEO storefronts; API for mobile; Blazor for rich .NET UI
Previous: Project Structure Explained
Next: Controllers and Actions
FAQ
Is MVC still used in .NET 8?
Yes — fully supported and widely used for server-rendered applications. Minimal APIs and Blazor are alternatives, not replacements for every scenario.
Can I mix MVC and Web API in one project?
Yes — call AddControllersWithViews() and map both controllers returning views and controllers returning JSON. ShopNest splits them into Web and API projects for clarity.