Blog

MVC vs MVVM

Key Takeaways

  • MVC separates model, view, and controller responsibilities; MVVM separates the model and view through UI-facing state and behavior in a view model.
  • MVVM doesn't require two-way binding. One-way state updates with explicit events or commands are also valid.
  • Server-rendered web MVC differs from classic desktop MVC. Always establish which variant you're comparing.
  • Modern Angular and Vue are component-based frameworks. Their binding features don't automatically make every application MVVM.
  • Choose boundaries around state ownership, interaction complexity, testing, and framework conventions—not pattern labels alone.

The central difference in MVC vs MVVM is how presentation behavior is organized: an MVC controller interprets input and coordinates a response, while an MVVM view model exposes state and actions that a view consumes. Both patterns separate application responsibilities, but MVVM isn't simply MVC with a renamed controller.

The boundaries can blur as applications grow. To compare the patterns usefully, ask where state lives, how an action changes it, and what causes the screen to update.

MVC Overview

MVC stands for Model–View–Controller. The MDN overview of MVC describes its central separation between business logic, display, and input-handling logic.

The Model

The model represents application data and domain behavior: the rules that remain meaningful without a particular screen. Users, posts, transactions, and shopping carts are examples of domain concepts.

Don't treat “Model” as a requirement to put everything into one database-backed class. Domain objects can enforce business rules, application services can coordinate a use case, and repositories can handle persistence. A repository is an abstraction for loading and saving data; it isn't the domain itself.

The View

The view defines how information is presented. It can be a server-side template, a desktop widget hierarchy, or another rendering mechanism.

A view doesn't universally update itself when model data changes. A server-rendered template produces output when invoked; an interactive view needs a mechanism such as notifications or an explicit render step.

For a login page, username and password fields are temporary form input. They don't imply that the view should map directly to a persisted user entity.

The Controller

The controller interprets input and coordinates the appropriate work. In web MVC, that commonly means receiving a routed request, calling application or domain behavior, and selecting a response or view.

Business rules don't need to live in the controller. Microsoft's ASP.NET Core MVC overview explicitly recommends moving business logic out of overloaded controllers and into the domain model.

MVC Has Multiple Variants

In classic desktop MVC, a controller interprets user interactions, and views can observe model changes. Apple's archived explanation of traditional and Cocoa MVC illustrates how even desktop implementations differ.

Server-rendered web MVC organizes work around requests and responses. Changing a server-side object doesn't, by itself, update a page already displayed in the browser. Confusing these variants produces misleading diagrams and comparisons.

Why MVC?

MVC remains a sensible choice for request-oriented applications: content pages, administrative interfaces, and workflows built around submitting forms and receiving responses. Its separation lets you change presentation without placing every layout decision alongside domain rules.

The cost is discipline. Controllers can become dumping grounds for validation, database queries, formatting, and business decisions. Keeping those responsibilities separate requires deliberate design; creating three folders doesn't accomplish it.

MVC also doesn't prescribe how a complex browser UI manages unsaved edits, selection, loading indicators, or optimistic changes. You still need a client-side state design when those interactions matter. Nor does separation of responsibilities require separate teams, services, or deployments.

Model View ViewModel (MVVM)

MVVM separates the domain model from the view through a view model: an object or module that presents UI-facing state and behavior. Microsoft's MVVM architecture guide describes the view model as an adapter between model data and what the UI needs.

What Belongs in a View Model?

A checkout view model might expose a formatted total, whether submission is available, validation feedback, and a submit action. Those are presentation concerns; calculating which discounts are legally applicable to an order belongs in domain behavior.

The view model coordinates model operations without depending on a particular view instance. The view chooses the markup, layout, and visual treatment. This boundary lets you test presentation behavior without constructing the screen.

A command is a named action such as save or add item. It can be exposed through a framework command interface or an ordinary method invoked by an event adapter.

Binding Direction Is an Implementation Choice

Data binding connects a state value to a UI property. One-way binding sends state to the view; two-way binding also sends edits back to the bound source. The .NET MAUI binding-mode documentation demonstrates both within MVVM-style interfaces.

MVVM doesn't require every editable value to use two-way binding. You can render state in one direction and handle user input through explicit events or commands. Prefer that approach when you need to trace changes, test action sequences, or distinguish editing a draft from committing it.

Two-way binding can still be convenient for local form fields. It doesn't mean those fields should write directly to persistent business data. For another perspective on explicit updates, see Flux vs MVC and one-way data flow.

MVC vs MVVM: State and Interaction Flow

This comparison uses two concrete variants: server-rendered web MVC and UI-level MVVM. It doesn't imply that MVC is limited to servers or MVVM to browsers.

ConcernServer-rendered MVCUI-level MVVM
Domain stateModel and application services provide the state used during a request.Model and application services provide the data presented through the view model.
Presentation stateRequest data and view-specific output describe the response being rendered.The view model holds or derives screen state, such as a draft or an available action.
User inputA routed request reaches a controller action.A view interaction invokes a command, event handler, or bound update.
Visible outputA view renders a response; the browser must receive that output.A binding or rendering mechanism consumes updated view-model state.
Useful testsController coordination, response selection, and domain behavior.State transitions, action availability, and domain behavior.
Server-rendered MVC                 UI-level MVVM
-------------------                 -------------
Input -> HTTP request               Input -> event / command
             |                                   |
             v                                   v
         Controller                          View model
             | calls                             | calls
             v                                   v
     Service / domain model              Service / domain model
             | result                            | result
             v                                   v
Controller -> View -> response          UI state -> binding/render -> View

The Same Interaction in Both Patterns

Consider adding one item to a cart, with an example business rule that caps quantity at five. Save this complete, dependency-free simulation as comparison.mjs and run node comparison.mjs.

The MVC view produces a text response. The MVVM view adapter prints presentation state. HTTP, persistence, and DOM widgets are deliberately omitted so the responsibility boundaries remain visible.

// Shared domain behavior. Inputs are trusted in-memory example data.
const initialCart = { quantity: 1 };

function canAddItem(cart) {
  return cart.quantity < 5;
}

function addItem(cart) {
  if (!canAddItem(cart)) return cart;
  return { quantity: cart.quantity + 1 };
}

// MVC: an action coordinates the model operation and response view.
function cartView(cart) {
  return `Quantity: ${cart.quantity}`;
}

function addItemController(cart) {
  const updated = addItem(cart);
  return { cart: updated, body: cartView(updated) };
}

console.log(addItemController(initialCart).body);

// MVVM: expose presentation state, an action, and change notifications.
function createCartViewModel(initial) {
  let cart = initial;
  const subscribers = new Set();

  function getState() {
    return {
      quantityLabel: `Quantity: ${cart.quantity}`,
      canAdd: canAddItem(cart),
    };
  }

  return {
    getState,
    subscribe(listener) {
      subscribers.add(listener);
      listener(getState());
      return () => subscribers.delete(listener);
    },
    add() {
      const updated = addItem(cart);
      if (updated === cart) return;
      cart = updated;
      for (const listener of subscribers) listener(getState());
    },
  };
}

// View-side adapter: a UI could render the label and button state here.
const vm = createCartViewModel(initialCart);
const unsubscribe = vm.subscribe((state) => {
  console.log(state.quantityLabel);
});
vm.add(); // Simulates a user action.
unsubscribe(); // Detach the view-side listener.

The output is:

Quantity: 2
Quantity: 1
Quantity: 2

The MVC action returns the updated model and a rendered response. The view model instead retains local state and exposes quantityLabel, canAdd, and add(); it never calls a particular view. The subscription supplies the notification mechanism, not two-way binding.

You can test the view model's quantity limit and action availability without a UI. A production implementation would also need explicit loading, persistence, and failure handling.

Defining Lines

Pattern boundaries can blur depending on application complexity and design goals. An object called a controller might accumulate presentation state, while an MVC application can legitimately pass a view-specific data object to a template.

In fact, ASP.NET Core MVC documentation uses the term ViewModel for data prepared for a view. That name alone doesn't establish an MVVM interaction architecture. Examine responsibilities and dependencies, not class names.

Angular Is Component-Based

Angular's component documentation describes applications as compositions of components with templates and behavior. A component can perform view-model-like work, but treating Angular as categorically MVC or MVVM obscures its actual conventions.

Specifically, [(ngModel)] belongs to template-driven forms and is provided by FormsModule. Reactive forms use explicit controls such as FormControl and FormGroup, with ReactiveFormsModule. The Angular forms overview distinguishes these approaches; neither proves that an application follows MVVM.

Keep modern Angular separate from its predecessor when interpreting older architecture discussions. Our Angular vs AngularJS comparison explains that distinction.

Vue Is MVVM-Inspired, Not a Universal MVVM Blueprint

Vue's older instance documentation explicitly describes MVVM as an inspiration rather than a strict association. Its current introduction emphasizes a declarative, component-based programming model and reactive updates.

Vue's state-management guide also explains a one-way cycle of state, view, and actions. Component structure and MVVM-inspired presentation boundaries can coexist; framework choice doesn't settle every state-management decision. For a framework-level comparison, see Vue vs React.

Combining MVC and MVVM at a Clear Boundary

A realistic combination is a server-side MVC application that renders an initial page and exposes endpoints used by a client-side MVVM-style screen. The server controller coordinates requests; the client view model manages drafts, pending operations, and display state.

Define the boundary explicitly: requests and responses form a contract, not a shared in-memory model. Keep authoritative business decisions on the server rather than trusting client-side presentation state.

Common Mistakes

  • Moving the same oversized class between patterns. Renaming a controller to a view model doesn't separate business rules from presentation behavior.
  • Duplicating derived state. Prefer deriving labels and action availability from their source values instead of maintaining competing copies.
  • Confusing binding with saving. Specify when a local edit becomes a committed change and what cancel means.
  • Ignoring asynchronous transitions. Test pending, failure, repeated-action, and out-of-order-response scenarios—not just successful updates.
  • Trusting browser validation. Enforce validation on the server; client checks can be bypassed, as the OWASP input-validation guidance explains.

When Should You Choose MVC or MVVM?

  • Start with MVC conventions when your framework and workflow are request-oriented and most interactions naturally end in a new response.
  • Consider MVVM-style boundaries when a screen has substantial editing, validation, pending state, or interaction behavior that deserves tests independent of rendering.
  • Follow your framework first. Don't introduce a view-model layer solely to rename a component, or dismantle a useful controller convention to satisfy a diagram.
  • Consider team familiarity and complexity. An extra abstraction should remove more coupling than it introduces.

For more on rendering, see our client-side vs server-side rendering comparison. The goal isn't the purest label—it's an architecture where state ownership and the path from input to output are easy to explain.

FAQ

What are the main differences between MVC and MVVM?

MVC separates model, view, and controller responsibilities, with the controller interpreting input and coordinating work. MVVM exposes UI-facing state and actions through a view model that the view consumes; it isn't merely a controller renamed.

Does MVVM require two-way data binding?

No. MVVM can use one-way state updates with explicit events or commands, two-way binding for editable properties, or a combination. Binding direction is an implementation choice, not the definition of the pattern.

Is Angular MVC, MVVM, or component-based?

Modern Angular is component-based. Components can take on view-model-like responsibilities, but template binding or ngModel alone doesn't establish an MVVM architecture.

Is Vue based on MVVM?

Vue is MVVM-inspired, not a strict implementation of a single MVVM architecture. Its current documentation emphasizes components, declarative rendering, and reactivity.

Can MVC and MVVM be used together?

Yes, at a clearly defined boundary—for example, server-side MVC handling requests while a client-side MVVM-style UI manages presentation state. Define the request contract, state ownership, and validation responsibilities rather than treating the combination as automatically coherent.

Further Reading

Written by Sam Erickson

Software engineer. I write every article on StackChief myself. Author of Mastering the Tech Interview. More about me