Skip to content

Architecture

High‑level view

The Cargonerds solution is built on top of the ABP Framework and uses a layered architecture. At the heart of the system lies the domain model and business logic. Around the domain layer are several projects that serve specific purposes: defining interfaces and DTOs, hosting application services, integrating with Entity Framework Core, exposing HTTP APIs and serving the user interface【405741767768697†L799-L846】. Each of these projects resides in its own assembly and references only the layers it requires, ensuring a clear separation of concerns.

While ABP defines how the application code is structured, .NET Aspire provides a unified way to run and observe all services. Aspire is described as an “opinionated, cloud‑ready stack” for building distributed applications with built‑in support for observability and resource modelling【798564215460282†L254-L259】. In this solution, the Cargonerds.AppHost project uses Aspire to declare resources such as SQL Server, Redis and RabbitMQ and to orchestrate the services that make up the application (AuthServer, HttpApi.Host, Web.Public, Blazor, NpmApp and DbMigrator). When run locally the AppHost spins up these resources (as Docker containers by default) and configures environment variables so that the services can find each other. When deployed to Azure, Aspire works with the Azure Developer CLI (azd) to provision equivalents such as Azure SQL, Azure Cache for Redis and Azure Container Apps.

The diagram below illustrates this high‑level structure. The services are grouped into three tiers: the orchestrator (AppHost) at the top, the application services in the middle and the infrastructure resources at the bottom. Solid arrows indicate primary dependencies (for example the AuthServer, HttpApi.Host, Web.Public and DbMigrator all depend on the database). Dashed and dotted arrows indicate ancillary connections such as frontend clients calling the API or services authenticating against the AuthServer. Redis and RabbitMQ are optional caches/messaging systems used by the services and are therefore not wired explicitly in the diagram.

High‑level architecture diagram

Layered architecture

ABP divides each module into a set of well‑defined layers. The main layers are summarised below. These descriptions are generic; they apply to both the main Cargonerds module and the Hub module.

.Domain.Shared project

This project contains constants, enums and simple types that belong to the domain but need to be shared with other layers. Since these values are used across the solution, every other project depends on .Domain.Shared but .Domain.Shared itself has no dependencies【405741767768697†L799-L808】.

.Domain project

The domain layer is the heart of the application. It contains entities, aggregate roots, domain services, value objects and repository interfaces【405741767768697†L810-L819】. Domain services encapsulate complex business rules that cannot naturally be placed in entities. The domain project depends only on .Domain.Shared so that it can reuse shared constants and enumerations.

.Application.Contracts project

This project defines the application service interfaces and the Data Transfer Objects (DTOs) used to communicate with clients. It separates the contract from the implementation, which allows the interfaces and DTOs to be shared with client applications without exposing the implementation details【405741767768697†L822-L833】.

.Application project

The application layer contains the concrete implementations of the application service interfaces. Application services orchestrate domain objects and enforce business rules by invoking domain services and repositories. This project depends on .Application.Contracts and the .Domain project because it needs to implement the contracts using domain objects【405741767768697†L836-L846】.

.EntityFrameworkCore project

This is the data access layer when using Entity Framework Core as the persistence provider. It defines the DbContext and implements repository interfaces defined in the domain layer【405741767768697†L848-L855】. The project depends on .Domain because it maps domain entities to database tables and implements repository methods.

.DbMigrator project

The DbMigrator is a console application used to create the database, apply migrations and seed initial data【405741767768697†L859-L884】. It is designed for both development and production: run it whenever you add a new migration or deploy to a fresh environment. The migrator depends on .EntityFrameworkCore to access migrations and on .Application.Contracts to grant permissions while seeding data【405741767768697†L881-L885】.

.HttpApi project

This project contains API controllers. ABP automatically generates API controllers for most application services, but you can manually create controllers here when needed【405741767768697†L887-L898】. It depends on .Application.Contracts so that controllers can call the application services.

.HttpApi.Client project

In some scenarios you may want to consume your APIs from a .NET client. The .HttpApi.Client project defines C# client proxies for your HTTP APIs【405741767768697†L899-L914】. You can reference this package from other .NET applications to call your own APIs without manually writing HTTP clients.

.UI projects

The user interface is implemented in two ways in this solution:

  • Web.Public – an ASP.NET Core MVC/Razor Pages application that provides the public web site. It references the .HttpApi layer to consume APIs and defines Razor pages, JavaScript and CSS resources【405741767768697†L919-L929】. In a tiered deployment the UI does not reference .Application or .EntityFrameworkCore, even though those references appear in the project file; they are only needed when the application is not deployed in a tiered manner【405741767768697†L931-L941】.
  • Blazor – a client‑side Blazor WebAssembly application. It references the .HttpApi.Client project to call the backend and uses ABP’s Blazor UI libraries. There is also a Cargonerds.Blazor.Client project which hosts the client code when running in ASP.NET Core.

In addition to these UI projects, there is a NpmApp under the AppHost which runs a Node‑based front‑end (for instance an Next.js application). The Npm app communicates with the backend through the HttpApi host and authenticates via the AuthServer.

Summary

The layered architecture ensures that responsibilities are clearly separated: business rules reside in the domain layer, application services orchestrate those rules, data access is isolated behind repositories, and presentation layers consume the APIs. .NET Aspire unifies the orchestration and deployment of these layers, making it easy to run the entire system on your development machine or in the cloud. For practical steps on how to run and deploy the system, see the Deployment guide.