Section 1 of 6

MVC Architecture

🎯 What You'll Learn

  • What is MVC
  • Model-View-Controller pattern
  • MVC vs Web API
  • Setting up MVC
  • Folder structure
  • Request pipeline

What is MVC?

MVC (Model-View-Controller) is a design pattern for building web applications that separates concerns into three components:

  • Model: Data and business logic
  • View: User interface (HTML)
  • Controller: Handles requests and coordinates Model and View
πŸ’‘ Key Concept

MVC separates your application into three distinct layers, making it easier to maintain, test, and scale.

The MVC Pattern

Model

The Model represents your data and business logic.

Models/Product.cs C#
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}

View

The View is the HTML template that displays data to the user.

Views/Products/Index.cshtml HTML
@model List<Product>

<h1>Products</h1>

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Price</th>
            <th>Quantity</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var product in Model)
        {
            <tr>
                <td>@product.Name</td>
                <td>@product.Price</td>
                <td>@product.Quantity</td>
            </tr>
        }
    </tbody>
</table>

Controller

The Controller handles HTTP requests and returns views.

Controllers/ProductsController.cs C#
public class ProductsController : Controller
{
    private readonly InvenTrackDbContext _context;

    public ProductsController(InvenTrackDbContext context)
    {
        _context = context;
    }

    public async Task<IActionResult> Index()
    {
        var products = await _context.Products.ToListAsync();
        return View(products);
    }
}

Request Flow

  1. User navigates to /Products
  2. Routing maps URL to ProductsController.Index()
  3. Controller retrieves data from database
  4. Controller passes data to View
  5. View renders HTML with data
  6. HTML is returned to the browser

MVC vs Web API

Aspect MVC Web API
Purpose Server-rendered HTML JSON/XML data
Base Class Controller ControllerBase
Returns IActionResult (Views) ActionResult<T> (Data)
Use Case Traditional web apps SPAs, mobile apps
Attributes Route attributes optional [ApiController] required

Setting Up MVC

Create MVC Project

Create Project Bash
dotnet new mvc -n InvenTrack.Web
cd InvenTrack.Web
dotnet run

Configure Services

Program.cs C#
var builder = WebApplication.CreateBuilder(args);

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

var app = builder.Build();

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

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

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

app.Run();

Folder Structure

InvenTrack.Web/
β”œβ”€β”€ Controllers/
β”‚   β”œβ”€β”€ HomeController.cs
β”‚   └── ProductsController.cs
β”œβ”€β”€ Models/
β”‚   β”œβ”€β”€ Product.cs
β”‚   └── ErrorViewModel.cs
β”œβ”€β”€ Views/
β”‚   β”œβ”€β”€ Home/
β”‚   β”‚   └── Index.cshtml
β”‚   β”œβ”€β”€ Products/
β”‚   β”‚   β”œβ”€β”€ Index.cshtml
β”‚   β”‚   └── Details.cshtml
β”‚   └── Shared/
β”‚       β”œβ”€β”€ _Layout.cshtml
β”‚       └── _ViewStart.cshtml
β”œβ”€β”€ wwwroot/
β”‚   β”œβ”€β”€ css/
β”‚   β”œβ”€β”€ js/
β”‚   └── lib/
β”œβ”€β”€ Program.cs
└── appsettings.json

Key Folders

Folder Purpose
Controllers/ MVC controllers
Models/ View models and entities
Views/ Razor view templates
Views/Shared/ Shared layouts and partials
wwwroot/ Static files (CSS, JS, images)

View Discovery

ASP.NET Core searches for views in this order:

  1. Views/{ControllerName}/{ActionName}.cshtml
  2. Views/Shared/{ActionName}.cshtml
Example C#
// ProductsController.Index() looks for:
// 1. Views/Products/Index.cshtml
// 2. Views/Shared/Index.cshtml

public IActionResult Index()
{
    return View(); // Searches for Index.cshtml
}

// Specify view name
public IActionResult Index()
{
    return View("ProductList"); // Searches for ProductList.cshtml
}

Complete InvenTrack Example

Models/Product.cs C#
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int Quantity { get; set; }
    public string Category { get; set; } = string.Empty;
}
Controllers/ProductsController.cs C#
public class ProductsController : Controller
{
    private readonly InvenTrackDbContext _context;

    public ProductsController(InvenTrackDbContext context)
    {
        _context = context;
    }

    // GET: /Products
    public async Task<IActionResult> Index()
    {
        var products = await _context.Products.ToListAsync();
        return View(products);
    }

    // GET: /Products/Details/5
    public async Task<IActionResult> Details(int id)
    {
        var product = await _context.Products.FindAsync(id);
        
        if (product == null)
            return NotFound();

        return View(product);
    }
}
Views/Products/Index.cshtml HTML
@model List<Product>

<h1>InvenTrack Products</h1>

<table class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Category</th>
            <th>Price</th>
            <th>Quantity</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var product in Model)
        {
            <tr>
                <td>@product.Name</td>
                <td>@product.Category</td>
                <td>$@product.Price</td>
                <td>@product.Quantity</td>
                <td>
                    <a asp-action="Details" asp-route-id="@product.Id">Details</a>
                </td>
            </tr>
        }
    </tbody>
</table>

Best Practices

  • Separation of concerns: Keep Models, Views, and Controllers separate
  • Thin controllers: Move business logic to services
  • View models: Use DTOs for views, not domain models
  • Async actions: Use async/await for database operations
  • Dependency injection: Inject services into controllers
  • Naming conventions: Follow ASP.NET Core conventions

Key Takeaways

  • MVC: Model-View-Controller design pattern
  • Model: Data and business logic
  • View: HTML templates (Razor)
  • Controller: Handles requests, returns views
  • AddControllersWithViews(): Registers MVC services
  • MapControllerRoute(): Configures routing
  • View discovery: Views/{Controller}/{Action}.cshtml
  • Server-rendered: HTML generated on server
🎯 Next Steps

You now understand MVC architecture! In the next section, we'll explore Controllers for Viewsβ€”action methods, action results, and passing data to views.