Skip to content

riannugraha/net-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

NetApi — .NET 10 Clean Architecture Boilerplate

A production-ready ASP.NET Core API built with Clean Architecture, CQRS with MediatR, OpenIddict (OAuth 2.0 / OpenID Connect), PostgreSQL, and the Repository pattern.


Architecture

src/
├── NetApi.Domain/          # Innermost layer — zero external dependencies
│   ├── Common/             # BaseEntity, shared abstractions
│   ├── Entities/           # Product, Customer, Order, OrderItem
│   ├── Enums/              # OrderStatus
│   └── Interfaces/         # IRepository<T>
├── NetApi.Application/     # Use cases — depends on Domain
│   ├── Common/
│   │   ├── Interfaces/     # IApplicationDbContext
│   │   └── Behaviors/      # ValidationBehavior (MediatR pipeline)
│   ├── Products/           # CQRS: Commands + Queries + DTOs
│   ├── Customers/          # CQRS: Commands + Queries + DTOs
│   ├── Orders/             # CQRS: Commands + Queries + DTOs
│   └── DependencyInjection.cs
├── NetApi.Infrastructure/  # EF Core, Identity, OpenIddict — depends on Application
│   ├── Data/
│   │   ├── AppDbContext.cs
│   │   ├── Configurations/ # EF Fluent API configs
│   │   └── Migrations/     # EF migrations
│   ├── Repositories/       # Repository<T> implementation
│   ├── Identity/           # ApplicationUser, OpenIddictSeeder
│   └── DependencyInjection.cs
└── NetApi.Api/             # Composition root — depends on Infrastructure
    ├── Controllers/        # ProductsController, CustomersController, OrdersController
    └── Program.cs           # DI wiring, middleware, OpenIddict config

Dependency Direction

Domain  ←  Application  ←  Infrastructure  ←  Api

Each layer can only reference layers inward. The Domain layer has zero dependencies.


Technologies

Component Library
Runtime .NET 10.0
Architecture Clean Architecture (Hexagonal)
CQRS MediatR 14.1
Validation FluentValidation 12.1
Mapping Mapster 10.0
ORM Entity Framework Core 10.0 (PostgreSQL)
Auth OpenIddict 7.5 (OAuth 2.0 + OpenID Connect)
Identity ASP.NET Core Identity
API Docs Swashbuckle 10.2 (Swagger)

Prerequisites

dotnet tool install --global dotnet-ef

Getting Started

1. Clone & Build

git clone <repo-url> NetApi
cd NetApi
dotnet build

2. Configure Connection String

Edit src/NetApi.Api/appsettings.json:

"ConnectionStrings": {
    "DefaultConnection": "Host=localhost;Port=5432;Database=netapi;Username=postgres;Password=postgres"
}

3. Apply Migrations

dotnet ef database update --project src/NetApi.Infrastructure --startup-project src/NetApi.Api

This creates all tables for:

  • Domain entities (Products, Customers, Orders, OrderItems)
  • ASP.NET Core Identity (AspNetUsers, AspNetRoles, etc.)
  • OpenIddict stores (OpenIddictApplications, OpenIddictTokens, etc.)

4. Run

dotnet run --project src/NetApi.Api

The API starts at https://localhost:5001 (or the port in launchSettings.json).

Swagger UI: https://localhost:5001/swagger


Authentication

This project uses OpenIddict as the OAuth 2.0 / OpenID Connect server. On first startup, the seeder creates:

Seeded Clients

Client ID Secret Grant Type Description
password-client password-secret-456 password + refresh_token First-party apps (mobile/web)
api-client api-secret-123 client_credentials Machine-to-machine

Seeded Users

Email Password Role
admin@netapi.dev Admin@123! Admin

Getting a Token

Password flow (user login):

curl -X POST https://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=password-client" \
  -d "client_secret=password-secret-456" \
  -d "grant_type=password" \
  -d "username=admin@netapi.dev" \
  -d "password=Admin@123!" \
  -d "scope=api"

Client credentials flow (machine-to-machine):

curl -X POST https://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=api-client" \
  -d "client_secret=api-secret-123" \
  -d "grant_type=client_credentials" \
  -d "scope=api"

Refresh token:

curl -X POST https://localhost:5001/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=password-client" \
  -d "client_secret=password-secret-456" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=<your-refresh-token>"

Using the Token

curl -X GET https://localhost:5001/api/products \
  -H "Authorization: Bearer <access-token>"

API Endpoints

All endpoints require Authorization: Bearer <token>.

Products

Method Path Description
GET /api/products List all products
GET /api/products/{id} Get product by ID
POST /api/products Create product
PUT /api/products/{id} Update product
DELETE /api/products/{id} Delete product

POST/PUT body:

{
  "name": "Widget",
  "description": "A useful widget",
  "price": 19.99,
  "stock": 100
}

Customers

Method Path Description
GET /api/customers List all customers
GET /api/customers/{id} Get customer by ID
POST /api/customers Create customer

POST body:

{
  "firstName": "John",
  "lastName": "Doe",
  "email": "john@example.com",
  "phone": "+1234567890"
}

Orders

Method Path Description
GET /api/orders List all orders (includes items)
GET /api/orders/{id} Get order by ID
POST /api/orders Create order

POST body:

{
  "customerId": "guid-here",
  "items": [
    { "productId": "guid-here", "quantity": 2 }
  ]
}

Project Commands

# Build
dotnet build

# Run
dotnet run --project src/NetApi.Api

# Add migration
dotnet ef migrations add <Name> --project src/NetApi.Infrastructure --startup-project src/NetApi.Api -o Data/Migrations

# Apply migrations
dotnet ef database update --project src/NetApi.Infrastructure --startup-project src/NetApi.Api

# Remove last migration
dotnet ef migrations remove --project src/NetApi.Infrastructure --startup-project src/NetApi.Api

Extending

Add a new domain entity

  1. Create entity in NetApi.Domain/Entities/
  2. Add DbSet<T> to IApplicationDbContext and AppDbContext
  3. Add EF configuration in NetApi.Infrastructure/Data/Configurations/
  4. Create CQRS in NetApi.Application/{Entity}/
  5. Create controller in NetApi.Api/Controllers/
  6. Add migration

Override OpenIddict configuration

The OpenIddict setup is in NetApi.Infrastructure/DependencyInjection.cs. Token lifetimes, grant types, and endpoint URIs can be modified there.

Production certificate

Replace AddDevelopmentEncryptionCertificate() / AddDevelopmentSigningCertificate() with AddEncryptionCertificate() / AddSigningCertificate() using production X.509 certificates stored in the machine store or Azure Key Vault.


License

MIT

About

.NET API

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages