← Back to Articles         
Entity vs Domain vs ViewModel vs DTO

Entity vs Domain vs ViewModel vs DTO

Published on 27 Sep 2026     8 min read ASP.NET Core MVC
MVC

Entity vs Domain Model vs ViewModel vs DTO

Type Main purpose Common layer Contains
Entity Represents data stored in the database Domain/Infrastructure Properties, primary key and relationships
Domain Model Represents business concepts and rules Domain Business data, behaviour and validation rules
ViewModel Provides data required by a specific View MVC presentation Display fields, form fields and UI validation
DTO Transfers data between layers, APIs or applications Application/API Only the required transferable data

1. Entity

Usually represents a database record and has an identity.

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

2. Domain Model

Represents business behaviour and protects business rules.

public class Order
{
    public decimal TotalAmount { get; private set; }

    public void ApplyDiscount(decimal percentage)
    {
        if (percentage is < 0 or > 50)
            throw new ArgumentException("Invalid discount.");

        TotalAmount -= TotalAmount * percentage / 100;
    }
}

An entity can also be a domain model. In a rich domain design, entities contain both identity and business behaviour.

3. ViewModel

Designed specifically for displaying or receiving data in an MVC View.

public class ProductViewModel
{
    public string Name { get; set; } = string.Empty;
    public string FormattedPrice { get; set; } = string.Empty;
    public List<string> Categories { get; set; } = [];
}

4. DTO

Transfers selected data between an API and its clients or between application layers.

public class ProductDto
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

Simple Flow

Database
   ↕
Entity / Domain Model
   ↕
Service
   ↙          ↘
ViewModel     DTO
MVC View      API Client

Key Points

  • Entity: Database identity and persistence.
  • Domain model: Business concepts, behaviour and rules.
  • ViewModel: Data shaped specifically for an MVC View.
  • DTO: Data shaped for transfer between boundaries.
  • Do not expose database entities directly to Views or API clients.
  • ViewModels and DTOs help prevent overposting and hide sensitive fields.
  • Mapping can be performed manually or with a mapping library.

Why Should Database Entities Not Be Passed Directly to Views?

Database entities represent the database structure. Views usually require data shaped specifically for the user interface. Therefore, pass a ViewModel to the View instead.

Main Problems

  • Security risk: Sensitive properties may be exposed accidentally.
  • Overposting: Users may submit values for fields they should not modify.
  • Tight coupling: Database changes directly affect the View.
  • Unnecessary data: The View may receive more fields than required.
  • UI-specific requirements: Display formatting and dropdown lists do not belong in an entity.
  • Validation differences: Database rules and UI validation rules may differ.
  • Maintainability: Entity-based Views become harder to change and test.

Example Entity

public class User
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string PasswordHash { get; set; } = string.Empty;
    public bool IsAdmin { get; set; }
}

Passing this entity directly could expose or bind sensitive fields such as:

PasswordHash
IsAdmin

Recommended ViewModel

public class EditUserViewModel
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; } = string.Empty;
}

Controller

public IActionResult Edit(int id)
{
    var user = _context.Users.Find(id);

    var viewModel = new EditUserViewModel
    {
        Id = user!.Id,
        Name = user.Name
    };

    return View(viewModel);
}

Key Points

  • Entities are designed for database persistence.
  • ViewModels are designed for UI display and input.
  • ViewModels expose only the required fields.
  • ViewModels help prevent overposting but must still be mapped safely.
  • Never trust posted identifiers or authorization-sensitive values; reload the entity and update only permitted fields.

What Is a Domain Model?

A domain model represents a real business concept along with its business rules and operations.

Here, domain means the business area of the application.

Examples:

Application domain Domain models
Banking Account, Transaction, Loan
Shopping Product, Order, Customer
Pension Member, Contribution, Benefit
Hospital Patient, Appointment, Prescription

Simple Banking Example

A bank account has data:

  • Account number
  • Balance

It also has business rules:

  • Deposit must be greater than zero.
  • Withdrawal cannot exceed the available balance.
public class BankAccount
{
    public int Id { get; private set; }
    public decimal Balance { get; private set; }

    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException(
                "Deposit amount must be greater than zero.");

        Balance += amount;
    }

    public void Withdraw(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Invalid amount.");

        if (amount > Balance)
            throw new InvalidOperationException(
                "Insufficient balance.");

        Balance -= amount;
    }
}

Here:

Balance                      → Business data
Deposit() and Withdraw()     → Business operations
Validation inside methods    → Business rules

Entity vs Domain Model

Entity Domain Model
Mainly represents stored data Represents the business concept
Usually contains properties Contains data, behaviour and rules
Often follows a database table Follows business requirements
May allow properties to be changed directly Protects data through business methods

Simple Entity

public class BankAccountEntity
{
    public int Id { get; set; }
    public decimal Balance { get; set; }
}

Anyone can incorrectly change the balance:

account.Balance = -50000;

Domain Model

account.Withdraw(5000);

The domain model verifies the business rules before changing the balance.

Important Clarification

An entity and domain model do not always have to be separate classes.

In a well-designed application, the same class can be both:

  • An entity because it has a unique identity such as Id.
  • A domain model because it contains business behaviour and rules.

Key Points

  • A domain model represents the business, not the screen.
  • It contains business data and business behaviour.
  • It prevents invalid business states.
  • Controllers should call domain or service methods instead of directly changing important values.
  • A model containing only public properties is commonly called an anemic domain model.
  • Domain models are especially useful for applications with complex business rules.

How Does Model Validation Work?

Model validation checks whether submitted data follows the validation rules defined in the model.

Validation Flow

Form Submission
      ↓
Model Binding
      ↓
Validation Attributes Checked
      ↓
Errors Added to ModelState
      ↓
Controller Checks ModelState.IsValid

ViewModel

public class ProductViewModel
{
    [Required(ErrorMessage = "Name is required.")]
    [StringLength(100)]
    public string Name { get; set; } = string.Empty;

    [Range(1, 100000)]
    public decimal Price { get; set; }
}

Controller

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(ProductViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    // Save valid data
    return RedirectToAction("Index");
}

View

<form asp-action="Create" method="post">
    <div asp-validation-summary="All"></div>

    <input asp-for="Name" />
    <span asp-validation-for="Name"></span>

    <input asp-for="Price" />
    <span asp-validation-for="Price"></span>

    <button type="submit">Save</button>
</form>

Common Validation Attributes

Attribute Purpose
[Required] Value must be provided
[StringLength] Controls string length
[Range] Defines numeric range
[EmailAddress] Validates email format
[Phone] Validates phone format
[Compare] Compares two properties
[RegularExpression] Validates against a pattern

Client-Side vs Server-Side Validation

Client-side Server-side
Runs in the browser Runs on the server
Gives immediate feedback Protects against invalid requests
Can be bypassed Cannot be trusted to the browser
Improves user experience Mandatory for security

Key Points

  • Model binding creates and populates the model first.
  • Validation runs after model binding.
  • Validation errors are stored in ModelState.
  • In an MVC controller, check ModelState.IsValid manually.
  • Return the same View with the submitted model when validation fails.
  • Always perform server-side validation.
  • Use a ViewModel for UI validation instead of adding every UI rule to database entities.
  • Complex business rules should also be enforced in the service or domain layer.

What Is ModelState?

ModelState stores the results of:

  • Model binding
  • Data conversion
  • Model validation

It contains both submitted values and validation errors.

Example

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(ProductViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    // Save valid data
    return RedirectToAction("Index");
}

Why Must It Be Checked?

  • Prevents invalid data from being saved.
  • Detects missing required fields.
  • Detects validation-attribute failures.
  • Detects type-conversion errors.
  • Returns validation messages to the View.
  • Improves data integrity and application security.

Example Validation Error

public class ProductViewModel
{
    [Required]
    public string Name { get; set; } = string.Empty;

    [Range(1, 100000)]
    public decimal Price { get; set; }
}

Invalid form data:

Name  = empty
Price = abc

ModelState contains:

  • Name validation error: value is required.
  • Price binding error: abc cannot be converted to decimal.
  • ModelState.IsValid becomes false.

Add a Custom Error

if (model.Price < 100)
{
    ModelState.AddModelError(
        nameof(model.Price),
        "Price must be at least 100.");
}

Model-level error:

ModelState.AddModelError(
    string.Empty,
    "Unable to save the product.");

Key Points

  • ModelState.IsValid is true only when there are no binding or validation errors.
  • Invalid models do not automatically stop normal MVC actions.
  • Return the same View with the model when validation fails.
  • Validation Tag Helpers display errors stored in ModelState.
  • Never save data before checking ModelState.IsValid.
  • [ApiController] usually returns HTTP 400 automatically for invalid API models; standard MVC controllers normally require a manual check.

 

← Back to Articles