Roadmap › .NET Full Stack Developer Interview — End to End › Module: End-to-End Request Flow
Lessons in this course (10)
5. Validation, error handling and logging across the layers
Intermediate★ Must knowLesson 5 of 10
Validate at every boundary — for different reasons:
| Layer | Validation | Why |
|---|---|---|
| UI | Reactive form validators / schema (Zod) | Fast feedback for the user |
| API | DataAnnotations or FluentValidation; [ApiController] returns 400 automatically | Never trust the client |
| Domain/service | Business rules (credit limit, status transitions) | Rules that need data |
| Database | NOT NULL, FK, UNIQUE, CHECK constraints | Last line of defence for integrity |
Consistent errors with ProblemDetails (RFC 9457):
csharp
builder.Services.AddProblemDetails();
builder.Services.AddExceptionHandler<GlobalExceptionHandler>();
app.UseExceptionHandler();
public sealed class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> log) : IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(HttpContext ctx, Exception ex, CancellationToken ct)
{
var (status, title) = ex switch
{
NotFoundException => (404, "Not found"),
ValidationException => (400, "Validation failed"),
_ => (500, "Unexpected error")
};
if (status == 500) log.LogError(ex, "Unhandled error for {Path}", ctx.Request.Path);
ctx.Response.StatusCode = status;
await ctx.Response.WriteAsJsonAsync(new ProblemDetails { Status = status, Title = title }, ct);
return true;
}
}UI side: one HTTP interceptor maps 400 → show field errors, 401 → refresh/login, 403 → "not allowed", 500 → toast + correlation id.
Logging: structured logs ({OrderId} placeholders, not string concatenation), a correlation id per request passed from UI to API to downstream services, log levels used properly, no passwords/tokens/PII in logs.