Skip to content

About

🍰 An asp.net core template based on .Net 10, Vertical Slice Architecture, CQRS, Minimal APIs, OpenTelemetry, API Versioning and OpenAPI.

Topics

Resources

Stars

264 stars

Watchers

7 watching

Forks

Latest commit

 

History

140 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Vertical Slice API Template

NuGet Build_Test Commitizen friendly

Open in GitHub Codespaces

An ASP.NET Core template based on Vertical Slice Architecture, CQRS, Minimal APIs, API versioning, OpenAPI, and .NET Aspire. Create a project from this template by clicking Use this template or installing the associated NuGet package.

⭐ Support

If you like feel free to ⭐ this repository, It helps out :)

Thanks a bunch for supporting me!

Table of Contents

Install

Install the .NET 10 SDK before using the template.

From NuGet

The template is published on NuGet.org as Vertical.Slice.ApiTemplate. You do not need to clone this repository.

  1. Install the latest stable template package:

    dotnet new install Vertical.Slice.ApiTemplate --nuget-source https://api.nuget.org/v3/index.json
  2. Verify that the template is available with the short name vsa:

    dotnet new list vsa
  3. Create a solution in a new folder, replacing MyProject with your project name:

    dotnet new vsa -n MyProject -o MyProject
    cd MyProject

To install a specific version, use Vertical.Slice.ApiTemplate@<version> instead of Vertical.Slice.ApiTemplate in the install command. Replace <version> with a version listed on the NuGet package page.

From a Local Clone

Clone this repository and run these commands from its root:

dotnet new install .
dotnet new vsa -n <YourProjectName>

Features

  • ✅ Vertical Slice Architecture with feature folders and CQRS
  • ✅ Mediator source generation for commands, queries, notifications, and pipeline behaviors
  • ✅ Minimal APIs with API versioning and OpenAPI documentation
  • ✅ Mapperly source-generated mappings and FluentValidation request validation
  • ✅ PostgreSQL persistence with Entity Framework Core, Dapper, SqlKata, and an in-memory option for local tests
  • ✅ Wolverine messaging with RabbitMQ, PostgreSQL message persistence, and transactional middleware
  • ✅ Hybrid caching with Redis support and MessagePack serialization
  • ✅ JWT authentication, authorization, CORS, header propagation, compression, rate limiting, and request timeouts
  • ✅ HTTP resilience using the .NET resilience libraries and Polly
  • ✅ Health checks with /health and /alive endpoints
  • ✅ OpenAPI tooling with Scalar, Swagger UI, and ReDoc
  • ✅ Generated API clients with Kiota and NSwag connected-service tooling
  • ✅ OpenTelemetry logs, metrics, and traces with OTLP export support
  • ✅ Local .NET Aspire orchestration with service discovery and dashboard diagnostics
  • ✅ Docker Compose and Kubernetes deployment assets
  • ✅ Unit, integration, contract, dependency, client, and end-to-end test projects

Libraries and Infrastructure

  • ✔️ .NET 10 - .NET runtime and ASP.NET Core target framework
  • ✔️ .NET Aspire - Local orchestration, service discovery, health checks, and dashboard
  • ✔️ Npgsql Entity Framework Core Provider - Npgsql has an Entity Framework (EF) Core provider. It behaves like other EF Core providers (e.g. SQL Server), so the general EF Core docs apply here as well
  • ✔️ FluentValidation - Popular .NET validation library for building strongly-typed validation rules
  • ✔️ Microsoft.AspNetCore.OpenApi - Built-in OpenAPI document generation
  • ✔️ Polly - Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner
  • ✔️ Wolverine - Messaging, handlers, and transactional middleware
  • ✔️ Scalar.AspNetCore - Interactive OpenAPI reference UI
  • ✔️ Scrutor - Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection
  • ✔️ Opentelemetry-dotnet - The OpenTelemetry .NET Client
  • ✔️ Newtonsoft.Json - Json.NET is a popular high-performance JSON framework for .NET
  • ✔️ AspNetCore.Diagnostics.HealthChecks - Enterprise HealthChecks for ASP.NET Core Diagnostics Package
  • ✔️ NSubstitute - A friendly substitute for .NET mocking libraries.
  • ✔️ StyleCopAnalyzers - An implementation of StyleCop rules using the .NET Compiler Platform
  • ✔️ Mapperly - A .NET source generator for generating object mappings, No runtime reflection.
  • ✔️ Mediator - A high performance implementation of Mediator pattern in .NET using source generators.
  • ✔️ NewID - NewId generates sequential unique identifiers that are 128-bit (16-bytes) and fit nicely into a Guid

Repository Tooling

The repository uses Husky.Net for Git hooks and task execution. The task definitions are in .husky/task-runner.json.

Restore the local tools and install the hooks with:

dotnet tool restore
dotnet tool run husky -- install

The configured tasks are:

Task Group Purpose
format pre-commit Run CSharpier over the repository.
style pre-commit Verify .NET style rules without changing files.
analyzers pre-commit Verify analyzer diagnostics at error severity.
build pre-push Build the Release configuration.
test pre-push Run the complete test suite.
build-ci ci Build Release without restoring packages.

The repository also provides equivalent mise tasks:

mise run restore
mise run build
mise run test
mise run quality

Testing

Tests use xUnit v3 with the xunit.v3.mtp-v2 integration package and are configured for Microsoft Testing Platform. The SDK and test runner are pinned in global.json, while the test projects enable Microsoft Testing Platform in tests/Directory.Build.props.

The test suite includes unit, integration, contract, dependency, generated-client, and end-to-end tests. Shared test infrastructure uses ASP.NET Core WebApplicationFactory, Testcontainers, WireMock.NET, Respawn, SQLite, FluentAssertions, and NSubstitute.

Run all tests from the repository root:

dotnet test --solution Vertical.Slice.ApiTemplate.sln --configuration Release

Docker is required for tests that start PostgreSQL, RabbitMQ, MongoDB, or SQL Server containers.

Getting Started

  1. This application uses Https for hosting apis, to setup a valid certificate on your machine, you can create a Self-Signed Certificate, see more about enforce certificate here.

  2. Install git - https://git-scm.com/downloads.

  3. Install the .NET 10 SDK - https://dotnet.microsoft.com/download/dotnet/10.0.

  4. Install Visual Studio, Rider or VSCode.

  5. Run dotnet new install Vertical.Slice.ApiTemplate to install the project templates.

  6. Now with running dotnet new --list, we should see Vertical.Slice.Template in the template list.

  7. Create a folder for your solution and cd into it (the template will use it as project name)

  8. Run dotnet new vsa -n <YourProjectName> for short name or dotnet new Vertical.Slice.Template -n <YourProjectName> to create a new project template.

  9. Open the generated solution and run dotnet build to verify it compiles.

  10. Run the API directly from the generated solution:

    dotnet run --project src/App/<YourProjectName>.Api
  11. Open http://localhost:4000/scalar for the Scalar API reference or http://localhost:4000/openapi/v1.json for the OpenAPI document.

Setup

Dev Certificate

This application uses Https for hosting apis, to setup a valid certificate on your machine, you can create a Self-Signed Certificate, see more about enforce certificate here and here.

dotnet dev-certs https --clean
dotnet dev-certs https -ep $env:USERPROFILE\.aspnet\https\aspnetapp.pfx -p <CREDENTIAL_PLACEHOLDER>
dotnet dev-certs https --trust
dotnet dev-certs https --clean
dotnet dev-certs https -ep ${HOME}/.aspnet/https/aspnetapp.pfx -p <CREDENTIAL_PLACEHOLDER>
dotnet dev-certs https --trust

dotnet dev-certs https --trust is only supported on macOS and Windows. You need to trust certs on Linux in the way that is supported by your distribution. It is likely that you need to trust the certificate in your browser(with this certificate we don't get an exception for https port because of not found certificate but browser shows us this certificate is not trusted).

Conventional Commits and Git Hooks

Commits follow Conventional Commits and are checked with commitlint. Git hooks are managed with Husky.Net rather than the Node.js Husky package.

After restoring tools, install the hooks:

dotnet tool restore
dotnet tool run husky -- install

The pre-commit hook runs formatting, style, and analyzer checks. The pre-push hook runs the Release build and complete test suite. See .husky/task-runner.json for the exact commands and file filters.

Application Structure

In this project I used vertical slice architecture or Restructuring to a Vertical Slice Architecture also I used feature folder structure in this project.

  • We treat each request as a distinct use case or slice, encapsulating and grouping all concerns from front-end to back.
  • When We adding or changing a feature in an application in n-tire architecture, we are typically touching many different "layers" in an application. we are changing the user interface, adding fields to models, modifying validation, and so on. Instead of coupling across a layer, we couple vertically along a slice and each change affects only one slice.
  • We Minimize coupling between slices, and maximize coupling in a slice.
  • With this approach, each of our vertical slices can decide for itself how to best fulfill the request. New features only add code, we're not changing shared code and worrying about side effects. For implementing vertical slice architecture using cqrs pattern is a good match.

Also here I used CQRS for decompose my features to very small parts that makes our application:

  • maximize performance, scalability and simplicity.
  • adding new feature to this mechanism is very easy without any breaking change in other part of our codes. New features only add code, we're not changing shared code and worrying about side effects.
  • easy to maintain and any changes only affect on one command or query (or a slice) and avoid any breaking changes on other parts
  • it gives us better separation of concerns and cross cutting concern (with help of Mediator behavior pipelines) in our code instead of a big service class for doing a lot of things.

With using CQRS, our code will be more aligned with SOLID principles, especially with:

  • Single Responsibility rule - because logic responsible for a given operation is enclosed in its own type.
  • Open-Closed rule - because to add new operation you don’t need to edit any of the existing types, instead you need to add a new file with a new type representing that operation.

Here instead of some Technical Splitting for example a folder or layer for our services, controllers and data models which increase dependencies between our technical splitting and also jump between layers or folders, We cut each business functionality into some vertical slices, and inner each of these slices we have Technical Folders Structure specific to that feature (command, handlers, infrastructure, repository, controllers, data models, ...).

Usually, when we work on a given functionality we need some technical things for example:

  • API endpoint (Controller)
  • Request Input (Dto)
  • Request Output (Dto)
  • Some class to handle Request, For example Command and Command Handler or Query and Query Handler
  • Data Model

Now we could all of these things beside each other and it decrease jumping and dependencies between some layers or folders.

Keeping such a split works great with CQRS. It segregates our operations and slices the application code vertically instead of horizontally. In Our CQRS pattern each command/query handler is a separate slice. This is where you can reduce coupling between layers. Each handler can be a separated code unit, even copy/pasted. Thanks to that, we can tune down the specific method to not follow general conventions (e.g. use custom SQL query or even different storage). In a traditional layered architecture, when we change the core generic mechanism in one layer, it can impact all methods.

High Level Structure

Modules Structure

Folder Structure

src
├───App
│   ├───Vertical.Slice.Template          # Catalog domain and vertical slices
│   └───Vertical.Slice.Template.Api      # ASP.NET Core API host
├───ApiClients
│   ├───Vertical.Slice.Template.ConnectedServiceClients
│   └───Vertical.Slice.Template.KiotaClients
├───Aspire
│   ├───Vertical.Slice.Template.AppHost
│   └───Vertical.Slice.Template.ServiceDefaults
└───Shared
    ├───Abstractions
    ├───Cache
    ├───Core
    ├───Diagnostics
    ├───EF
    ├───HealthCheck
    ├───Logging
    ├───Messaging.Wolverine
    ├───OpenApi
    ├───RateLimit
    ├───Resiliency
    ├───Validation
    └───Web

Vertical Slice Flow

Each feature groups its request, handler, endpoint, DTOs, mapping, and persistence concerns under the feature area. Shared cross-cutting behavior lives in src/Shared; hosting and orchestration live in src/App and src/Aspire.

How to Run

Open Vertical.Slice.ApiTemplate.sln in Visual Studio, Rider, or VS Code and run the Aspire AppHost for the complete local environment.

Using .NET Aspire

The Aspire AppHost starts the API together with PostgreSQL 17 and RabbitMQ 4. It also provides service discovery, health checks, and the Aspire dashboard.

From the repository root, run:

dotnet run --project src/Aspire/Vertical.Slice.Template.AppHost

Use the dashboard URL printed by Aspire to inspect resources, logs, traces, and health. The API resource is registered as catalogs-api; the database and broker resources are registered as catalogsdb and rabbitmq.

To run only the API without Aspire infrastructure, use:

dotnet run --project src/App/Vertical.Slice.Template.Api

Contribution

The application is in development status. You are feel free to submit pull request or create the issue.

License

The project is under MIT license.

About

🍰 An asp.net core template based on .Net 10, Vertical Slice Architecture, CQRS, Minimal APIs, OpenTelemetry, API Versioning and OpenAPI.

Topics

Resources

Stars

264 stars

Watchers

7 watching

Forks

Releases

Packages

Used by

Contributors

Languages

⌂ 换网址