Skip to content

iPazooki/CleanArchitecture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub GitHub contributors .NET Aspire CI

Clean Architecture

A lightweight .NET 10 based Clean Architecture template leveraging Minimal API and .NET Aspire. This repository helps you quickly set up a maintainable project structure that separates core business rules from infrastructure and presentation concerns while taking advantage of Aspire's cloud-native tooling.

Why This Template?

  • Faster Development: Pre-configured with essential design patterns like CQRS (Commands/Queries), value objects, and layered architecture.
  • Domain-Driven Design: Organize your core business logic with Entities, Value Objects, Specifications, and Domain Services.
  • Cloud-Ready with .NET Aspire: Uses an Aspire AppHost to orchestrate services, dependencies, health checks, and observability.
  • Postgres by Default: Uses PostgreSQL as the primary relational database (via EF Core) for local development and deployment.
  • Simple API: Minimal API endpoints keep things lightweight and easy to extend.
  • Extensible: Easily add new modules, microservices, or features without breaking existing code.
  • Scalable: Clear separation of concerns keeps your code well-organized as your app grows.
  • Robust Testing: Includes example unit tests (using xUnit and Moq) and integration tests.
  • Polly Integration: Resilient API calls with built-in retries, circuit breaker patterns, and fallbacks.

Project Structure

  1. Domain Layer
    • Entities, value objects, and domain services.
  2. Application Layer
    • Interfaces, DTOs, commands, queries, and validators.
  3. Infrastructure Layer
    • Persistence, database repositories, and external service integrations.
  4. Infrastructure.Persistence Layer
    • EF Core DbContext, Postgres configuration, and migrations.
  5. Presentation Layer
    • Minimal API endpoints, middleware, and request/response handling.
  6. Aspire AppHost
    • .NET Aspire AppHost project that wires up the API, Postgres, and shared service defaults.

Getting Started

The following prerequisites are required to build and run the solution:

  1. Clone the repository to your local machine.
    • git clone https://github.com/iPazooki/CleanArchitecture.git
    • git clone git@github.com:iPazooki/CleanArchitecture.git
  2. Navigate to the project directory.
  3. Restore dependencies using:
    • dotnet restore

Running with .NET Aspire (recommended)

The solution is configured to run using .NET Aspire via the AppHost project.

  1. From the solution root, run the AppHost project:
    • dotnet run --project CleanArchitecture.Aspire/CleanArchitecture.AppHost/CleanArchitecture.AppHost.csproj
  2. Aspire will:
    • Start the CleanArchitecture.Presentation minimal API.
    • Provision and start a Postgres container/instance (as configured in the AppHost).
    • Apply service defaults (health checks, telemetry, etc.).
  3. Once running, navigate to the API Swagger UI (the port may vary depending on Aspire configuration). By default this is similar to:
    • https://localhost:7281/swagger/index.html

Running the API Project Directly (without Aspire)

If you prefer to run only the API (and manage Postgres yourself):

  1. Ensure you have a running Postgres instance and that the connection string in CleanArchitecture.Presentation/API/appsettings.json points to it.
  2. Build and run the application:
    • dotnet build
    • dotnet run --project CleanArchitecture.Presentation
  3. Visit the Swagger UI (by default):
    • https://localhost:7281/swagger/index.html

Deployment to Azure with azd

The Aspire AppHost is configured for Azure deployment through azd.

Prerequisites

  • Azure CLI
  • Azure Developer CLI (azd)
  • .NET Aspire workload

Deploy

From the solution root, run:

azd up

During deployment, azd will provision the Azure resources defined by CleanArchitecture.Aspire/CleanArchitecture.AppHost/AppHost.cs, including:

  • Azure Container Apps for the API, admin app, and Keycloak
  • Azure Database for PostgreSQL Flexible Server
  • Azure Key Vault
  • Azure Application Insights

Parameters requested by azd

azd up should prompt only for values that cannot be derived automatically:

nextAuthSecret
keycloakClientId
keycloakClientSecret
keycloakRealm
keycloakAdminUsername
keycloakAdminPassword

Public URLs

The following public application URLs are now derived automatically from the Azure Container Apps external endpoints during manifest generation and deployment:

  • adminPublicUrl
  • apiPublicUrl
  • authPublicUrl

You should no longer need to enter those values manually during azd up.

If you later want to use custom domains instead of the default Azure Container Apps hostnames, update the production environment configuration in CleanArchitecture.Aspire/CleanArchitecture.AppHost/AppHost.cs and your Azure Container Apps ingress/domain settings accordingly.

Authentication

This project integrates with Keycloak for authentication. Before running the API with secured endpoints you must provide a client secret for the scalar client in Keycloak and store it in the project's user secrets.

Important: for Visual Studio users you can set secrets via the Manage User Secrets UI. The instructions below assume the client in Keycloak is named scalar.

Steps to create and configure a new Client Secret

  1. Open your Keycloak admin panel (the instance URL configured for your environment) and select clean-api realm.
  2. Go to the Clients section and select the scalar client.
  3. Open the Credentials (or Client Secrets) tab for that client.
  4. Create/regenerate a new client secret and copy the secret value.

Store the secret in Visual Studio (recommended)

  1. In Visual Studio, right-click the CleanArchitecture.Api project and select Manage User Secrets.
  2. In the JSON editor that opens, add an entry for the client secret. Example structure: { "ScalarApi:ClientSecret": "YourClientSecret" }

Store the secret in the file system (optionally)

  1. Use the dotnet user-secrets CLI tool to set the secret from the terminal/command prompt:
dotnet user-secrets set "ScalarApi:ClientSecret" "<your-client-secret-here>" --project CleanArchitecture.Api

Admin Portal Configuration

The project includes an admin dashboard located in CleanArchitecture.Presentation/admin. To run the admin portal, you need to configure the environment variables in a .env.local file.

  1. Navigate to the admin directory:
    cd CleanArchitecture.Presentation/admin
  2. Create or update the .env.local file with the following configurations:
API_BASE_URL=http://localhost:5049/

NEXTAUTH_URL=http://localhost:65499
NEXTAUTH_SECRET=<random string>

KEYCLOAK_CLIENT_ID=scalar
KEYCLOAK_CLIENT_SECRET=<client secret>
KEYCLOAK_ISSUER=http://localhost:8080/realms/clean-api

Where to find these values:

  • API_BASE_URL: The base URL where your CleanArchitecture API is running.
  • NEXTAUTH_URL: The URL of your admin portal (used for authentication callbacks).
  • NEXTAUTH_SECRET: A random secret string used to hash tokens. You can generate one using node -e "console.log(require('crypto').randomBytes(32).toString('hex'))".
  • KEYCLOAK_CLIENT_ID: The client ID configured in Keycloak (e.g., scalar).
  • KEYCLOAK_CLIENT_SECRET: The client secret from your Keycloak client's Credentials tab.
  • KEYCLOAK_ISSUER: The issuer URL of your Keycloak realm (e.g., http://localhost:8080/realms/clean-api).

Database Configuration

  • Database: PostgreSQL
  • EF Core Provider: Npgsql.EntityFrameworkCore.PostgreSQL
  • Configuration: Connection strings are defined in CleanArchitecture.Presentation/API/appsettings.json and can be overridden in environment-specific files like CleanArchitecture.Presentation/API/appsettings.Development.json or via Aspire resource configuration in CleanArchitecture.Aspire/CleanArchitecture.AppHost/appsettings*.json.

Database Migrations

Migrations are managed using Entity Framework Core and are stored in the CleanArchitecture.Infrastructure.Persistence project.

Design-Time Migrations

Because .NET Aspire injects connection strings at runtime, the standard EF Core tools cannot find a database connection during design-time. To solve this, the project includes an ApplicationDbContextFactory which provides a dummy connection string for the tools.

To add a new migration, run the following command from the solution root:

dotnet ef migrations add <MigrationName> --project CleanArchitecture.Infrastructure.Persistence --startup-project CleanArchitecture.Presentation/API

Applying Migrations

Development and Testing

In non-production environments, migrations are automatically applied during application startup using context.Database.MigrateAsync() in CleanArchitecture.Presentation/API/Configuration/WebApplicationExtensions.cs.

Manual Update

If you need to manually update the database:

dotnet ef database update --project CleanArchitecture.Infrastructure.Persistence --startup-project CleanArchitecture.Presentation/API

Ensure a PostgreSQL instance is reachable if you are running this manually outside of the Aspire orchestrator.

Contributing

Pull requests are welcome! For major changes, please open an issue first to discuss proposed modifications. We appreciate your support and feedback. Don’t forget to star the project if you find it helpful.

License

This project is licensed under the MIT license. Feel free to use it as a foundation for your own projects!

About

Clean Architecture with Minimal API

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Contributors