Understanding ViewModels in ASP.NET

ViewModels are a crucial pattern in modern web development, especially within frameworks like ASP.NET MVC and ASP.NET Core. They play a vital role in separating concerns between the presentation layer (views) and the business logic/data access layer (models).

What is a ViewModel?

A ViewModel is a plain class that holds data specifically intended for display in a particular view or a set of related views. It acts as an intermediary, shaping the data from your domain models into a format that the view can easily consume. Unlike domain models, which represent the core business entities, ViewModels are tailored to the specific needs of the user interface.

Why Use ViewModels?

Creating a ViewModel

Creating a ViewModel is straightforward. You typically define a class in your project that contains properties matching the data required by your view. There's no special base class or attribute required; it's just a C# class.

Example: Product Listing ViewModel

Let's say we have a `Product` domain model and we want to display a list of products with their name, price, and whether they are in stock. We can create a ViewModel like this:


public class ProductListItemViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string FormattedPrice => Price.ToString("C"); // Example of data formatting
    public bool IsInStock { get; set; }
    public string StockStatus => IsInStock ? "In Stock" : "Out of Stock";
}

public class ProductListViewModel
{
    public List<ProductListItemViewModel> Products { get; set; }
    public string PageTitle { get; set; }
}
            

Populating a ViewModel

In your controller action (or Razor Page handler), you'll retrieve data from your domain models and map it to your ViewModel. This mapping process can be done manually, or using libraries like AutoMapper.

Example: Controller Action


// Assume ProductService retrieves products from the database
public class ProductController : Controller
{
    private readonly IProductService _productService;

    public ProductController(IProductService productService)
    {
        _productService = productService;
    }

    public IActionResult Index()
    {
        var products = _productService.GetAllProducts(); // Get domain models

        var viewModel = new ProductListViewModel
        {
            PageTitle = "Our Amazing Products",
            Products = products.Select(p => new ProductListItemViewModel
            {
                Id = p.Id,
                Name = p.Name,
                Price = p.Price,
                IsInStock = p.StockQuantity > 0
            }).ToList()
        };

        return View(viewModel); // Pass ViewModel to the view
    }
}
            

Using ViewModels in the View

In your Razor view, you declare the ViewModel type at the top and then access its properties directly.

Example: Product List View (.cshtml)


@model ProductListViewModel

@{
    ViewData["Title"] = Model.PageTitle;
}

<h1>@Model.PageTitle</h1>

<table class="table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Price</th>
            <th>Status</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var product in Model.Products)
        {
            <tr>
                <td><a asp-controller="Product" asp-action="Details" asp-route-id="@product.Id">@product.Name</a></td>
                <td>@product.FormattedPrice</td>
                <td>@product.StockStatus</td>
            </tr>
        }
    </tbody>
</table>
            

Important Note:

ViewModels should generally be read-only from the perspective of the view for display purposes. If the view needs to submit data back to the server, a separate ViewModel for input (often called an InputModel or FormModel) should be used.

Tip:

Consider using a tool like AutoMapper to simplify the process of mapping between your domain models and ViewModels, especially in larger applications.

Common ViewModel Scenarios

By embracing the ViewModel pattern, you create more organized, maintainable, and robust ASP.NET applications.