Start here. This is the direct spoken answer to practice first.
Why this question matters
Validation is not one middleware step. A useful design separates malformed input, contract rules, current-state decisions, domain invariants, authorization, and race-safe database enforcement so each failure has the right owner and response.
I split validation by responsibility. Model binding and the request DTO handle shape, required values, lengths, formats, and ranges. The application layer checks rules that need current state, such as whether an order is still editable. Domain code protects invariants that must hold regardless of whether the caller is HTTP, a job, or a message handler. Authorization stays separate, and database constraints remain the final defense for uniqueness and concurrent writes.