.NET Learning
BookStore.Api
A learning project for building a REST API with ASP.NET Core, PostgreSQL, repositories, services, and controllers.
The goal is to get familiar with patterns, validation, dependency injection, and database integration without using an ORM like Entity Framework.
Key Learnings
- Data annotation
Used for automatic validation at the API boundary. Once DTOs are introduced, these live on the DTOs instead of the domain models, keeping the models clean and focused only on business rules. - Dependency injection (DI)
Services and repositories are always registered by their interfaces, not their concrete implementations. This makes it easy to swap in different implementations (e.g. a mock repository for testing, Postgres in production). - Repository, service, controller pattern (close to MVC)
- Repository → handles SQL queries and database access.
- Service → business logic and rules outside of basic validation.
- Controller → handles the HTTP layer, maps DTOs to models, and returns responses.
This is sometimes just called MVC, though the service layer is often skipped in the strict pattern.
- Data Transfer Objects (DTOs)
These are the contract between the API and the outside world.- DTOs contain validation attributes like
[Required],[Range]. - Models (domain objects) stay free of annotations.
- Controllers handle binding between DTOs and models.
- DTOs contain validation attributes like
- Naming conventions
- JSON in REST APIs is typically camelCase (e.g.
publishedOn). - PostgreSQL uses snake_case (e.g.
published_on).
It looks inconsistent at first, but it’s the normal convention.
- JSON in REST APIs is typically camelCase (e.g.
- Secrets management
Instead of putting passwords intoappsettings.json, secrets are stored locally with the .NET user-secrets feature:dotnet user-secrets initdotnet user-secrets set "ConnectionStrings:DefaultConnection" "Host=localhost;Port=5432;Database=bookstore;Username=postgres;Password=yourpassword"
This keeps sensitive credentials out of git. - Program.cs as the entry point
Very similar to Go’smain.go. This is where DI is wired up for repos, services, controllers, and the application is started. - Built-in API behavior
ASP.NET Core takes care of a lot of the response boilerplate:400 Bad Requestwhen validation fails.404 Not Foundwithreturn NotFound().200 OKwithreturn Ok(obj).201 CreatedwithCreatedAtAction().
Compared to Go, this means less hand-rolled response handling.
- Layer responsibilities
- Repository: queries + persistence.
- Service: rules and logic beyond DTO validation.
- Controller: DTO binding and HTTP response formatting.
Stack
- ASP.NET Core Web API
- PostgreSQL
- Npgsql (no ORM, raw SQL)