Skip to main content

Model-View-Controller (MVC)

MVC splits an app into model (data and rules), view (presentation), and controller (input handling) for independent, maintainable parts. It is the default architecture for server-rendered web frameworks, with MVP and MVVM as client-focused descendants.

Type
Architectural
When to Use
Separate UI From Logic, Structure Web Applications, Support Multiple Views, Improve Maintainability

Model-View-Controller (MVC) is a foundational architectural pattern that divides an application into three roles. The model holds data and business rules; the view renders state to the user; the controller interprets user input and orchestrates the other two. The separation lets each part change independently and supports multiple views over the same model.

How It Works

A user interacts with the view, which forwards input to the controller. The controller updates the model — applying validation and business logic — and selects which view to render. The view reads from the model to display current state. In the classic Smalltalk formulation the model notifies views of changes via the observer pattern; in web MVC frameworks the cycle is request-driven instead: a request hits a controller action, which loads or mutates models and returns a view (template) to render.

Server-side MVC dominates web frameworks: Ruby on Rails, ASP.NET MVC/Core, Spring MVC, Laravel, and Django (often called MTV) all map routes to controller actions that render views from models. Each request is stateless and produces a fresh view.

When to Use It

MVC fits applications with clear separation between data, presentation, and interaction — most server-rendered web apps and many desktop frameworks. It helps teams divide work (designers on views, engineers on models), supports several presentations of one model, and keeps business logic out of the UI. It is the default mental model for request/response web frameworks.

Trade-offs

The boundaries blur in practice. Controllers tend to accumulate logic that belongs in models or services ("fat controllers"), and the model layer can become a catch-all. In rich client UIs the original observer-driven MVC is awkward, which is why derivatives like MVP and MVVM emerged for stateful, event-heavy interfaces. The term is also used loosely, so two "MVC" frameworks may differ substantially.

Related Patterns

MVP and MVVM are direct descendants that reshape the controller's role for client-side UIs. The observer pattern underlies classic MVC's model-to-view notifications. On the frontend, the container/presentational split echoes MVC's separation of logic from rendering. Modernizing efforts such as ASP.NET MVC 5 → ASP.NET Core or Spring MVC → Spring WebFlux keep the pattern while updating the runtime.

Example

// ASP.NET Core controller
public class ProductsController : Controller {
    private readonly IProductService _service;
    public ProductsController(IProductService service) => _service = service;

    public IActionResult Details(int id) {
        var product = _service.GetById(id);   // model
        if (product is null) return NotFound();
        return View(product);                  // view
    }
}

The controller handles the request, asks the service/model for data, and hands a model to the view to render — the three roles cleanly separated.