Skip to content

pmdevers/dotnet-project-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

16 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

.NET Project Template

A modern, scalable .NET template featuring Domain-Driven Design (DDD), Event Sourcing, CQRS patterns, and .NET Aspire orchestration.

🎯 Features

  • Domain-Driven Design (DDD): Well-structured domain models with aggregates and value objects
  • Event Sourcing: Full audit trail with event-based aggregate persistence
  • CQRS: Separated read and write models
  • Event Bus: In-memory event publishing and subscription
  • Entity Framework Core: PostgreSQL with EF Core migrations
  • .NET Aspire: Container orchestration with Redis and PostgreSQL
  • OpenAPI: Built-in API documentation with Scalar
  • Serilog: Structured logging
  • Vue.js: Modern frontend with Vite
  • .NET 10: Latest C# features and performance improvements

πŸš€ Quick Start

Prerequisites

  • .NET 10 SDK
  • Docker & Docker Compose (for Aspire)
  • PowerShell

1. Clone the Repository

git clone https://github.com/pmdevers/dotnet-project-template.git
cd dotnet-project-template

2. Run with .NET Aspire

The easiest way to run the entire stack:

dotnet run --project src/AppHost/Template.AppHost.csproj

This starts:

  • PostgreSQL database
  • Redis cache
  • ASP.NET Core API
  • Vue.js frontend

3. Access the Application

πŸ“ Project Structure

src/
β”œβ”€β”€ AppHost/              # .NET Aspire orchestration
β”œβ”€β”€ Api/                  # ASP.NET Core API
β”‚   β”œβ”€β”€ Domain/          # Business logic (entities, aggregates, value objects)
β”‚   β”œβ”€β”€ Infrastructure/  # Data access, events, repositories
β”‚   β”œβ”€β”€ Features/        # API endpoints and command handlers
β”‚   └── Configuration/   # Service and middleware setup
β”œβ”€β”€ WebUi/               # Vue.js frontend
β”œβ”€β”€ ServiceDefaults/     # Shared configuration
└── Generators/          # Source generators

πŸ—οΈ Architecture

Domain Layer

  • Aggregates: Car, Reservation
  • Value Objects: LicensePlate
  • Events: CarRegistered, ReservationCreated, etc.

Infrastructure Layer

  • Data: AppDbContext with EF Core for PostgreSQL
  • Events: Event sourcing tables and queries
  • EventBus: Async event publishing and subscription
  • Migrations: Database schema versioning

Features

  • Cars: Register and query vehicles
  • Reservations: Create and retrieve reservations (event-sourced)

πŸ—„οΈ Database

Migrations

Two migrations are included:

  1. InitialCreate: Creates Cars table
  2. EventSourcedAggregate: Creates Events table for event sourcing

Apply migrations automatically on startup via AppDbContextMigrationService.

Connection String

Via .NET Aspire:

var postgres = builder.AddPostgres("appdb");

Automatically injected as ConnectionStrings:appdb

Manual setup:

"ConnectionStrings": {
  "appdb": "Host=localhost;Database=streamsharp;Username=postgres;Password=postgres"
}

πŸ“ Key Patterns

Event Sourcing Example

// Create a reservation (event-sourced aggregate)
var reservation = Reservation.Create(customerId, carId, startDate, endDate);
var repo = serviceProvider.GetRequiredService<IRepository<Reservation, ReservationId>>();
repo.Add(reservation);
await unitOfWork.SaveChangesAsync();

// Load from history
var loaded = await repo.TryFindAsync(reservation.Id);

CQRS Pattern

// Command: create via endpoint
app.MapPost("/reservations", CreateReservation.Handle);

// Query: read via ICarQueries or EventQueries
var cars = await carQueries.GetAllAsync();
var reservation = await dbContext.GetAggregate<Reservation>(id);

Event Bus

// Subscribe to events
services.AddEventBus();

// Publish automatically on domain events
await unitOfWork.SaveChangesAsync(); // Triggers event dispatch

πŸ› οΈ Common Tasks

Add a New Aggregate

  1. Create entity in Domain/Entities
  2. Create configuration in Infrastructure/Data/Config
  3. Add DbSet<T> to AppDbContext
  4. Create migration: dotnet ef migrations add YourMigrationName

Add an Endpoint

  1. Create feature in Features/
  2. Implement handler with dependency injection
  3. Register in ApiEndpoints.cs

Subscribe to Domain Events

// In EventBusExtensions.cs
bus.Subscribe<CarRegistered>(async @event =>
{
    logger.LogInformation("Car registered: {@Event}", @event);
});

πŸ“¦ NuGet Packages

Core dependencies:

  • Microsoft.EntityFrameworkCore (10.0.0)
  • Npgsql.EntityFrameworkCore.PostgreSQL
  • Microsoft.AspNetCore.OpenApi
  • Serilog & related sinks

πŸ§ͺ Testing

# Run all tests
dotnet test

# Run specific test project
dotnet test src/Api/Template.Api.csproj

πŸ“– API Documentation

After running the app, visit:

πŸ› Troubleshooting

Database connection fails

  • Ensure PostgreSQL is running (via Aspire or Docker)
  • Check POSTGRES_CONNECTION_STRING environment variable

Migrations don't apply

  • Delete AppDbContextMigrationService output and retry
  • Verify EF Core tools: dotnet ef --version

Aspire not found

  • Update .NET: dotnet --version should be 10.0.0+
  • Reinstall: dotnet tool update -g dotnet-aspire-latest

🀝 Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Commit changes
  4. Push and open a pull request

πŸ“„ License

This project is open source and available under the MIT License.

πŸ“š Resources


Created by: @pmdevers

Repository: https://github.com/pmdevers/dotnet-project-template

About

A modern, scalable .NET template featuring Domain-Driven Design (DDD), Event Sourcing, CQRS patterns, and .NET Aspire orchestration.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

 
 
 

Contributors