DEV Community

Cover image for Hands-on project comparation MVVM and MVC in C#
Taki
Taki

Posted on

Hands-on project comparation MVVM and MVC in C#

Let's walk through two mini projects side-by-side in C# — one using MVC for a web app (ASP.NET Core), and another using MVVM for a desktop app (WPF). Both will manage a simple Product with properties like Name and Price.


🔷 PROJECT 1: ASP.NET Core MVC Web App

✅ Goal:

A web interface to view and create products using the MVC pattern.

🔧 Tech Stack:

  • ASP.NET Core MVC (.NET 8+)
  • Razor Views

📁 Folder Structure:

MvcProductApp/ │ ├── Controllers/ │ └── ProductController.cs ├── Models/ │ └── Product.cs ├── Views/ │ └── Product/ │ ├── Index.cshtml │ └── Create.cshtml ├── Startup.cs or Program.cs (depending on template) 
Enter fullscreen mode Exit fullscreen mode

📄 Models/Product.cs

public class Product { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } 
Enter fullscreen mode Exit fullscreen mode

📄 Controllers/ProductController.cs

public class ProductController : Controller { private static List<Product> products = new(); public IActionResult Index() { return View(products); } [HttpGet] public IActionResult Create() { return View(); } [HttpPost] public IActionResult Create(Product product) { products.Add(product); return RedirectToAction("Index"); } } 
Enter fullscreen mode Exit fullscreen mode

📄 Views/Product/Index.cshtml

@model List<Product> <h2>Product List</h2> <a href="/Product/Create">Create Product</a> <ul> @foreach (var product in Model) { <li>@product.Name - $@product.Price</li> } </ul> 
Enter fullscreen mode Exit fullscreen mode

📄 Views/Product/Create.cshtml

@model Product <h2>Create Product</h2> <form asp-action="Create" method="post"> <input asp-for="Name" placeholder="Name" /> <input asp-for="Price" placeholder="Price" /> <button type="submit">Save</button> </form> 
Enter fullscreen mode Exit fullscreen mode

Run this in your browser. It uses classic MVC:

  • Controller mediates between View and Model.
  • No live data-binding or client-side state.

🔷 PROJECT 2: WPF MVVM Desktop App

✅ Goal:

A WPF desktop app where you can bind textboxes to a ProductViewModel using MVVM.

🔧 Tech Stack:

  • WPF App (.NET 8+)
  • MVVM with INotifyPropertyChanged and ICommand

📁 Folder Structure:

MvvmProductApp/ │ ├── Models/ │ └── Product.cs ├── ViewModels/ │ └── ProductViewModel.cs ├── Views/ │ └── MainWindow.xaml ├── RelayCommand.cs └── App.xaml.cs / MainWindow.xaml.cs 
Enter fullscreen mode Exit fullscreen mode

📄 Models/Product.cs

public class Product { public string Name { get; set; } public decimal Price { get; set; } } 
Enter fullscreen mode Exit fullscreen mode

📄 RelayCommand.cs

public class RelayCommand : ICommand { private readonly Action _execute; public RelayCommand(Action execute) => _execute = execute; public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) => true; public void Execute(object parameter) => _execute(); } 
Enter fullscreen mode Exit fullscreen mode

📄 ViewModels/ProductViewModel.cs

public class ProductViewModel : INotifyPropertyChanged { private string _name; private decimal _price; public string Name { get => _name; set { _name = value; OnPropertyChanged(nameof(Name)); } } public decimal Price { get => _price; set { _price = value; OnPropertyChanged(nameof(Price)); } } public ICommand SaveCommand { get; } public ProductViewModel() { SaveCommand = new RelayCommand(SaveProduct); } private void SaveProduct() { MessageBox.Show($"Product saved: {Name}, ${Price}"); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } 
Enter fullscreen mode Exit fullscreen mode

📄 Views/MainWindow.xaml

<Window x:Class="MvvmProductApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MvvmProductApp" Title="MVVM Product App" Height="200" Width="300"> <Window.DataContext> <local:ProductViewModel /> </Window.DataContext> <StackPanel Margin="20"> <TextBox Text="{Binding Name, Mode=TwoWay}" PlaceholderText="Product Name" /> <TextBox Text="{Binding Price, Mode=TwoWay}" PlaceholderText="Price" /> <Button Content="Save" Command="{Binding SaveCommand}" /> </StackPanel> </Window> 
Enter fullscreen mode Exit fullscreen mode

This is classic MVVM:

  • ViewModel handles logic and exposes data.
  • View binds to ViewModel (no event handlers in code-behind).
  • Supports real-time UI updates and data validation.

🧠 Final Thoughts

Feature ASP.NET MVC WPF MVVM
UI Update Method Server-driven (postbacks) Data binding (live updates)
Logic Separation Controller-centric ViewModel-centric
Platform Web Desktop/mobile
Testability Controller unit test ViewModel unit test

Top comments (0)