6. REST API, DTO & Validation

ASP.NET Core REST APIs, DTOs & Validation - Complete Guide

Practical Guide + Technical Reference


📋 Table of Contents

Part 1: Practical Guide (Hands-On)

  1. REST API Fundamentals

  2. Building REST APIs (3 Approaches)

  3. DTOs (Data Transfer Objects)

  4. Model Validation (3 Methods)

  5. Content Negotiation

  6. Error Handling & Problem Details

  7. API Versioning

  8. Swagger/OpenAPI Documentation

  9. Troubleshooting Common Issues

  10. Best Practices

Part 2: Technical Reference (Deep Dive)

  1. Important Interfaces & Classes Reference

  2. Configuration Deep-Dive

  3. Advanced Topics


PART 1: PRACTICAL GUIDE


1. REST API Fundamentals

Simple Definition: REST (Representational State Transfer) is an architectural style for building web APIs using HTTP methods.

Think of it like: A restaurant menu where:

  • URLs are dishes (resources)

  • HTTP methods are actions (order, modify, cancel)

  • Status codes are feedback (success, error, not found)

HTTP Methods (Verbs)

Method
Purpose
Example
Idempotent*

GET

Retrieve data

Get user by ID

✅ Yes

POST

Create new resource

Create new user

❌ No

PUT

Update/Replace entire resource

Update all user fields

✅ Yes

PATCH

Update partial resource

Update user email only

❌ No

DELETE

Remove resource

Delete user

✅ Yes

*Idempotent = Multiple identical requests have same effect as single request

HTTP Status Codes

Success (2xx):

  • 200 OK - Request succeeded (GET, PUT, PATCH)

  • 201 Created - Resource created (POST)

  • 204 No Content - Success with no response body (DELETE)

Client Errors (4xx):

  • 400 Bad Request - Invalid input/validation failed

  • 401 Unauthorized - Authentication required

  • 403 Forbidden - Authenticated but not authorized

  • 404 Not Found - Resource doesn't exist

  • 409 Conflict - Resource conflict (duplicate)

Server Errors (5xx):

  • 500 Internal Server Error - Unhandled exception

  • 503 Service Unavailable - Service down

RESTful URL Design Principles

Good:

Bad:

Key Principles:

  1. Use nouns, not verbs (users, not getUsers)

  2. Use plural nouns (users, not user)

  3. Use HTTP methods for actions

  4. Keep URLs hierarchical (users/5/orders)

  5. Use lowercase and hyphens (user-profiles, not UserProfiles)


2. Building REST APIs (3 Approaches)

Method 1: Minimal APIs ✨ (.NET 6+) - Quick

When to use:

  • ✅ Small APIs (5-10 endpoints)

  • ✅ Microservices

  • ✅ Prototyping/Learning

  • ❌ Complex business logic

  • ❌ Large applications (20+ endpoints)

Step 1: Basic Setup

Step 2: Define Endpoints

Step 3: Complete CRUD Example with Database


When to use:

  • ✅ Most production APIs

  • ✅ Complex business logic

  • ✅ Large applications

  • ✅ Need filters, authorization

  • ✅ Team development

Step 1: Create Controller

Step 2: Register in Program.cs

Step 3: Complete CRUD Controller with Best Practices


Method 3: MVC Controllers - Full MVC

When to use:

  • ✅ Mixed API + web pages

  • ✅ Server-side rendering

  • ❌ Pure APIs (use ApiController instead)


Comparison: Which Approach?

Feature
Minimal APIs
API Controllers ⭐
MVC Controllers

Setup

Simplest

Medium

Complex

Code Lines

Fewest

Moderate

Most

Filters/Attributes

Limited

Full support ✅

Full support ✅

Model Binding

Basic

Full ✅

Full ✅

Validation

Basic

Full ✅

Full ✅

Testing

Harder

Easy ✅

Easy ✅

Organization

Inline

Files/Folders ✅

Files/Folders ✅

Performance

Fastest

Fast

Fast

Best For

Small APIs

Production APIs ✅

Web + API

Decision Tree:


3. DTOs (Data Transfer Objects)

What are DTOs? Objects designed specifically for transferring data between layers or over the network.

Why use DTOs?

  1. Security - Don't expose internal models (hide sensitive fields)

  2. Versioning - API changes don't break database models

  3. Performance - Send only what's needed

  4. Clarity - Different shapes for different operations

The Problem Without DTOs

The Solution With DTOs

Step 1: Create DTOs for Different Operations

Step 2: Use DTOs in Controller


Mapping DTOs (3 Methods)

Method 1: Manual Mapping - Simple

When to use:

  • ✅ Small projects

  • ✅ Simple mappings

  • ✅ Learning

  • ❌ Large projects

  • ❌ Complex mappings

Pros: No dependencies, simple, clear Cons: Repetitive, error-prone, tedious


When to use:

  • ✅ Production applications

  • ✅ Many DTOs

  • ✅ Complex mappings

  • ✅ Consistent mapping logic

Step 1: Install Package

Step 2: Create Mapping Profile

Step 3: Register in Program.cs

Step 4: Use in Controller


Method 3: Mapster - Fast & Simple

When to use:

  • ✅ Performance critical

  • ✅ Simpler than AutoMapper

  • ✅ Less configuration

Step 1: Install Package

Step 2: Configure Mappings

Step 3: Use in Controller


Mapping Comparison

Feature
Manual
AutoMapper ⭐
Mapster

Setup

None

Medium

Simple

Performance

Fastest

Good

Faster

Flexibility

Limited

High ✅

Medium

Learning Curve

Easiest

Medium

Easy

Configuration

None

Required

Optional

Community

N/A

Large ✅

Growing

Best For

Small projects

Production ✅

Performance


4. Model Validation (3 Methods)

What is validation? Ensuring data meets business rules before processing.

When to use:

  • ✅ Simple validation rules

  • ✅ Quick setup

  • ✅ Standard validation

  • ❌ Complex business logic

  • ❌ Cross-property validation

Step 1: Add Attributes to DTO

Step 2: Validation Happens Automatically with [ApiController]

Step 3: Custom Error Response (Optional)

Built-in Validation Attributes Reference:

Attribute
Purpose
Example

[Required]

Field must have value

[Required]

[StringLength]

String length limits

[StringLength(100, MinimumLength = 2)]

[Range]

Numeric range

[Range(1, 100)]

[EmailAddress]

Valid email format

[EmailAddress]

[Phone]

Valid phone number

[Phone]

[Url]

Valid URL

[Url]

[RegularExpression]

Matches regex pattern

[RegularExpression(@"^\d{5}$")]

[Compare]

Matches another property

[Compare("Password")]

[CreditCard]

Valid credit card

[CreditCard]

[MinLength]

Minimum collection size

[MinLength(1)]

[MaxLength]

Maximum collection size

[MaxLength(10)]


When to use:

  • ✅ Complex business rules

  • ✅ Cross-property validation

  • ✅ Reusable validation logic

  • ✅ Testable validators

  • ✅ Production applications

Step 1: Install Package

Step 2: Create Validator Class

Step 3: Register in Program.cs

Step 4: Use in Controller (Automatic)

Step 5: Manual Validation (Optional)

Advanced FluentValidation Examples:


Method 3: Custom Validation Attributes - Reusable

When to use:

  • ✅ Reusable validation logic

  • ✅ Attribute-based approach preferred

  • ✅ Simple to medium complexity

Step 1: Create Custom Attribute

Step 2: Use Custom Attributes


Validation Comparison

Feature
Data Annotations
FluentValidation ⭐
Custom Attributes

Setup

None

Package install

Create classes

Complexity

Simple

Complex ✅

Medium

Async Validation

Limited

Full support ✅

Supported

Testability

Hard

Easy ✅

Medium

Separation of Concerns

Mixed

Clean ✅

Mixed

Cross-property

Limited

Easy ✅

Medium

Dependency Injection

Limited

Full ✅

Limited

Best For

Simple validation

Production apps ✅

Reusable rules

Decision Tree:


5. Content Negotiation

What is content negotiation? The process of selecting the best representation of a resource based on client preferences (JSON, XML, etc.)

Default: JSON

Supporting XML

Step 1: Add XML Support

Step 2: Client Requests XML

Response:

Force Specific Format

Custom Formatters


6. Error Handling & Problem Details

The Problem Without Error Handling

Method 1: Try-Catch in Controller

Step 1: Create Exception Middleware

Step 2: Register in Program.cs

Step 3: Use in Controllers


Method 3: Problem Details (RFC 7807) ⭐ - Standard

What is Problem Details? A standard format for HTTP API error responses defined in RFC 7807.

Step 1: Enable Problem Details

Step 2: Return Problem Details

Response:

Step 3: Custom Problem Details


Error Response Comparison

Approach
Consistency
Complexity
Standard
Best For

Try-Catch

Low

Simple

No

Small projects

Global Middleware

High ✅

Medium

No

Custom needs

Problem Details

High ✅

Medium

Yes ✅

Production ⭐


7. API Versioning

Why version APIs?

  • Breaking changes without affecting existing clients

  • Gradual migration path

  • Support multiple versions simultaneously

Step 1: Install Package

Step 2: Configure Versioning

Step 3: Create Versioned Controllers

Usage:


Method 2: Query String Versioning

Usage:


Method 3: Header Versioning

Usage:


Versioning Comparison

Method
Pros
Cons
Best For

URL

Clear, cacheable, browser-friendly

URLs change

Public APIs

Query String

Clean URLs, flexible

Not RESTful, harder to cache

Internal APIs

Header

Clean URLs, RESTful

Not browser-friendly

Advanced clients


8. Swagger/OpenAPI Documentation

What is Swagger? Interactive API documentation that lets developers test endpoints in browser.

Step 1: Add Swagger (Included in Web API template)

Step 2: Add XML Documentation Comments

Enable XML documentation:

Add XML comments to controllers:

Configure Swagger to use XML comments:

Step 3: Add Response Examples

Access Swagger UI

Navigate to: https://localhost:5001/ (if RoutePrefix set to empty) Or: https://localhost:5001/swagger


9. Troubleshooting Common Issues

Issue 1: Validation Not Working

Problem:

Solution:


Issue 2: 415 Unsupported Media Type

Problem: Client sends JSON but server rejects it.

Solution:


Issue 3: Null Values in Request

Problem:

Solutions:


Issue 4: Circular Reference in JSON

Problem:

Solutions:


Issue 5: CORS Errors

Problem:

Solution:


10. Best Practices

✅ Do's

  1. Use DTOs for API contracts

  2. Use appropriate HTTP status codes

  3. Version your APIs

  4. Document with Swagger

  5. Validate input

  6. Use async/await

  7. Log appropriately

  8. Use pagination for lists

❌ Don'ts

  1. Don't expose database models directly

  2. Don't ignore validation

  3. Don't use verbs in URLs

  4. Don't return 200 for errors

  5. Don't forget authorization


PART 2: TECHNICAL REFERENCE


11. Important Interfaces & Classes Reference

ControllerBase Class ⭐⭐⭐

Purpose: Base class for API controllers (no view support)

Namespace: Microsoft.AspNetCore.Mvc

Key Members:

Member
Type
Purpose

Request

HttpRequest

Current HTTP request

Response

HttpResponse

Current HTTP response

User

ClaimsPrincipal

Current authenticated user

ModelState

ModelStateDictionary

Model validation state

HttpContext

HttpContext

Current HTTP context

Action Result Methods:

Method
Status Code
Purpose

Ok(object)

200

Success with data

Created(string, object)

201

Resource created

CreatedAtAction(string, object, object)

201

Created with location

NoContent()

204

Success, no content

BadRequest(object)

400

Invalid request

Unauthorized()

401

Authentication required

Forbid()

403

Not authorized

NotFound(object)

404

Resource not found

Conflict(object)

409

Resource conflict

StatusCode(int, object)

Custom

Custom status code

Problem(ProblemDetails)

Varies

Problem details response

Complete Example:


IActionResult Interface ⭐⭐⭐

Purpose: Represents the result of an action method

Namespace: Microsoft.AspNetCore.Mvc

Common Implementations:

Class
Status
Usage

OkResult

200

return Ok();

OkObjectResult

200

return Ok(data);

CreatedResult

201

return Created(uri, data);

CreatedAtActionResult

201

return CreatedAtAction(...);

NoContentResult

204

return NoContent();

BadRequestResult

400

return BadRequest();

BadRequestObjectResult

400

return BadRequest(error);

UnauthorizedResult

401

return Unauthorized();

ForbidResult

403

return Forbid();

NotFoundResult

404

return NotFound();

NotFoundObjectResult

404

return NotFound(message);

ConflictResult

409

return Conflict();

ConflictObjectResult

409

return Conflict(error);

StatusCodeResult

Custom

return StatusCode(500);

ObjectResult

Custom

return StatusCode(500, error);

FileResult

200

return File(bytes, contentType);

JsonResult

200

return Json(data);

RedirectResult

302

return Redirect(url);

Usage Examples:


ActionResult Class ⭐⭐⭐

Purpose: Generic action result that can return either T or IActionResult

Namespace: Microsoft.AspNetCore.Mvc

Why use it?

  • Better OpenAPI/Swagger documentation

  • Type-safe return values

  • Implicit conversion from T

Usage:

With async:


ModelStateDictionary Class ⭐⭐

Purpose: Contains validation errors

Namespace: Microsoft.AspNetCore.Mvc.ModelBinding

Key Members:

Member
Type
Purpose

IsValid

bool

True if no errors

ErrorCount

int

Number of errors

Keys

IEnumerable

Property names with errors

Values

IEnumerable

Validation entries

Usage:


ProblemDetails Class ⭐⭐

Purpose: Standard error response format (RFC 7807)

Namespace: Microsoft.AspNetCore.Mvc

Properties:

Property
Type
Purpose

Type

string

URI identifying problem type

Title

string

Short summary

Status

int?

HTTP status code

Detail

string

Detailed explanation

Instance

string

URI of specific occurrence

Extensions

IDictionary

Additional data

Usage:


ValidationProblemDetails Class ⭐⭐

Purpose: Problem details for validation errors

Namespace: Microsoft.AspNetCore.Mvc

Extends: ProblemDetails

Additional Property:

Property
Type
Purpose

Errors

IDictionary<string, string[]>

Validation errors by field

Usage:


12. Configuration Deep-Dive

Pattern 1: Inline Configuration

When to use: Simple, hardcoded settings


Pattern 2: Constructor Options

When to use: Code-based configuration

Step 1: Create Options Class

Step 2: Register

Step 3: Inject


Pattern 3: IOptions from appsettings.json ⭐

When to use: Production configuration

Step 1: appsettings.json

Step 2: Options Classes

Step 3: Register

Step 4: Use


IOptions vs IOptionsSnapshot vs IOptionsMonitor

Feature

IOptions

IOptionsSnapshot

IOptionsMonitor

Lifetime

Singleton

Scoped

Singleton

Reload

No

Per request

Live

When to use

Static config

Per-request reload

Background services

Usage Example:


13. Advanced Topics

Pagination Helper


HATEOAS (Hypermedia)


Response Caching


Rate Limiting (.NET 7+)


Summary: Complete API Development Checklist

Planning:

Implementation:

Documentation:

Security:

Testing:

Production:


This completes the REST APIs, DTOs & Validation guide with practical examples and comprehensive technical reference!

Last updated