The application layer
Validation and ProblemDetails
Returning errors consistently, machine-readably and safely.
Understand the concept
There are two kinds of validation. Shape validation checks the form of input: required, acceptable length, e-mail format. Data annotations ([Required], [MaxLength], [EmailAddress]) do this during model binding and [ApiController] returns an invalid request with 400 automatically. Business validation checks rules: is this slug already taken, does this user own this resource. These checks belong in the service layer.
Error responses use the RFC 9457 ‘Problem Details’ standard: type, title, status, detail and optional extensions. For validation errors an ‘errors’ object carries field-level messages that the client can show next to the matching form fields. A traceId lets you find the related log entry when a user reports a problem.
Pick the status code carefully: a shape error is 400, a conflict (duplicate slug) 409, a missing resource 404. Error messages should tell the user what to do but never leak internals (SQL, stack traces, file paths).
A consistent error format simplifies client code and speeds up support.
Returning every error as 200 with { success: false }; caches, monitoring and clients treat it as success.
A letter’s journey through the city
Think of a request as a letter and the server as a city. Pick a scenario, press play and watch which gates the letter passes and where it gets stopped.
The contact form is sent, but the e-mail field says ‘ayse-at-ornek’.
One topic. Three levels of depth.
public sealed record CreatePost(
[Required, MaxLength(160)] string Title,
[Required, RegularExpression("^[a-z0-9-]+$")] string Slug);Shape rules sit on the request model.
This page connects to no real server or database. Code samples are illustrative for .NET 8, Next.js and SQL Server; timings are example values in the simulation, not measurements. Try samples only in your own development environment; never share real connection strings, tokens or passwords.
Try it yourself first.
A create-post request arrives: the title is empty and the slug is already used. Which error returns first, with which status code?
Show the solution and explanation
Önce biçim doğrulaması çalışır: boş başlık → 400 (ValidationProblemDetails, errors.Title).
İstek controller’a ulaşmadığı için slug çakışması kontrol edilmez.
Başlık düzeltilip tekrar gönderilince slug çakışması → 409.Shape validation runs during binding and business validation inside the service; since they are sequential, the first failure decides the response.