- Notifications
You must be signed in to change notification settings - Fork74
Vertical Slice Architecture solution template in .NET 9
License
nadirbad/VerticalSliceArchitecture
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Check out my blog postA Guide to Vertical Slice Architecture in C# .NET for more details about Vertical Slice Architecture.
This project is an experiment trying to create an API solution template that uses a Vertical Slice architecture style.
The Vertical Slice architecture style is about organizing code by features and vertical slices instead of organizing by technical concerns. It's about an idea of grouping code according to the business functionality and putting all the relevant code close together.Vertical Slice architecture can be a starting point and can be evolved later when an application becomes more sophisticated:
We can start simple (Transaction Script) and simply refactor to the patterns that emerges from code smells we see in the business logic.Vertical slice architecture by Jimmy Bogard.
Loving it? Show your support by giving this project a star!
This project repository is created based onClean Architecture solution template by Jason Taylor, and it uses technology choices and application business logic from this template.
- ASP.NET API with .NET 9
- CQRS withMediatR
- FluentValidation
- Entity Framework Core 9
- xUnit,FluentAssertions,Moq
- Result pattern for handling exceptions and errors usingErrorOr package
Afterwards, the projects and architecture is refactored towards the Vertical slice architecture style.
Most applications start simple but they tend to change and evolve over time. Because of this, I wanted to create a simpler API solution template that focuses on the vertical slices architecture style.
Typically if I need to change a feature in an application, I end up touching different layers of the application and navigating through piles of projects, folders, and files.
The goal is to stop thinking about horizontal layers and start thinking about vertical slices and organize code byFeatures. When the code is organized by feature you get the benefits of not having to jump around projects, folders, and files. Things related to given features are placed close together.
When moving towards the vertical slices we stop thinking about layers and abstractions. The reason is the vertical slice doesn't necessarily need shared layer abstractions like repositories, services, controllers. We are more focused on concrete behavior implementation and what is the best solution to implement.
The solution template is broken into 2 projects:
ASP.NET Web API project is an entry point to the application, but it doesn't have any controllers, all the controller actions are moved to theApplication project features.
This project contains all application logic and shared concerns like Domain Entities, Infrastructure, and other common concerns. All the business logic is placed in aFeature
folder. Instead of having a file for basically controller, command/query, validator, handlers, and models, I placed everything usually in one file, and have all the relevant things close together.
- Install the latest.NET 9 SDK
- Navigate to
src/Api
and rundotnet run
to launch the back end (ASP.NET Core Web API) or viadotnet run --project src/Api/Api.csproj
CLI commands executed from the root folder.
# builddotnet build# rundotnet run --project src/Api/Api.csproj# run unit testsdotnettest tests/Application.UnitTests/Application.UnitTests.csproj# run integrations tests (required database up and running)dotnettest tests/Application.IntegrationTests/Application.IntegrationTests.csproj# publishdotnet publish src/Api/Api.csproj --configuration Release
To run API locally, for example, to debug them, you can use the VS Code (just open and press F5) or other IDE (VisualStudio, Rider).By default, the project uses in-memory database, but if you would like to change that check the next section aboutDatabase Configuration
To run the project from the terminal
dotnet run --project src/Api/Api.csproj
and you'll be good to go everything will be up and running. Go the the indicated URLhttps://localhost:7098/ and you'll see the API Swagger UI.
The project is configured to use an in-memory database by default. So you can run the project without additional infrastructure (SQL Server)
If you would like to use SQL Server, you will need to updateApi/appsettings.json as follows:
"UseInMemoryDatabase":false,
Verify that theDefaultConnection connection string withinappsettings.json points to a valid SQL Server instance.
When you run the application the database will be automatically created (if necessary) and the latest migrations will be applied.
The solution I work with is running Azure SQL Edge in Docker as a database for local development and testing. In the following section, I'll describe the steps needed to setup SQL Edge:
Docker is a great way to play with SQL Server without the administrative overhead of managing an instance.
Azure SQL Edge is a way to test and develop using SQL Server locally, and have a consistent experience between machines, whether they're PCs running Windows, Intel-based Macs, or the new Apple silicon M1 (there are no Docker images for SQL Server that support ARM64 just yet).
We'll need Docker first to get started – easiest is to installDocker Desktop.
With Docker up and running, next we need to pull the most recent Azure SQL Edge container image:
sudo docker pull mcr.microsoft.com/azure-sql-edge:latest
We can create and start the appropriate container with the following command:
sudo docker run --cap-add SYS_PTRACE -e'ACCEPT_EULA=1' -e'MSSQL_SA_PASSWORD=yourStrong(!)Password' -p 1433:1433 --name azuresqledge -d mcr.microsoft.com/azure-sql-edge
I decided to use Azure SQL Edge as flavor of SQL Server in Docker, and enable local development and testing no matter which OS you're running.
To usedotnet-ef
for your migrations please add the following flags to your command (values assume you are executing from repository root)
--project src/Application
(optional if in this folder)--startup-project src/Api
--output-dir Infrastructure/Persistence/Migrations
For example, to add a new migration from the root folder:
dotnet ef migrations add"InitialMigration" --project src/Application --startup-project src/Api --output-dir Infrastructure/Persistence/Migrations
and apply migration and update the database:
dotnet ef database update --project src/Application --startup-project src/Api
You can test the endpoints using tools likePostman or simply from VS Code using theREST Client extension.
Find the example requests in therequests
folder in the root of the project.
Developers should follow Microsoft'sC# Coding Conventions.
To enforce consistent coding styles and settings in the codebase, we use an EditorConfig file (.editorconfig) prepopulated with the default.NET code style, formatting, and naming conventions.
Forcode analysiswe use the built-in analyzers.
IMPORTANT NOTES:
- EditorConfig settings take precedence over global IDE text editor settings.
- New lines of code are formatted according to the EditorConfig settings
- The formatting of existing code is not changed unless you run:
dotnet format
from the command line
There are a few arguments we can supply to the dotnet format command to control its usage. A useful one is the--verify-no-changes argument
. This argument is useful when we want to understand when code breaks standards, but not automatically clean it up.
dotnet format --verify-no-changes
Both code formating and analysis can be performed from the cli by running:
dotnet format styledotnet format analyzers
or to execute both
dotnet format
- Clean Architecture solution template by Jason Taylor
- Vertical slice architecture by Jimmy Bogard
- Organize code by Feature using Vertical Slices by Derek Comartin
This project is licensed with theMIT license.
About
Vertical Slice Architecture solution template in .NET 9
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.