Cargonerds module¶
The Cargonerds module is the core application in this solution. It is implemented as a tiered ABP application, meaning that the backend services (AuthServer and HttpApi.Host) can be deployed separately from the user interfaces (Web.Public, Blazor and an optional NPM client). Each project follows the layered structure described in the architecture overview【405741767768697†L799-L846】, and .NET Aspire is used to orchestrate all the services and infrastructure required at runtime 【798564215460282†L254-L259】.
Projects and their roles¶
The table below lists each project in the src directory and gives a
short description of its purpose. The names follow the ABP convention
(for example *.Domain, *.Application, *.HttpApi) and each
implements one layer of the domain‑driven design.
| Project | Purpose |
|---|---|
| Cargonerds.Domain.Shared | Holds constants, enums, settings and localisation resources that must be shared across layers. This project has no dependencies and is referenced by all other projects【405741767768697†L799-L808】. |
| Cargonerds.Domain | Contains the domain model: entities (such as Book), value objects, repository interfaces and domain services【405741767768697†L810-L819】. Business rules live here and this project depends only on .Domain.Shared. |
| Cargonerds.Application.Contracts | Defines the application service interfaces and Data Transfer Objects (DTOs) used to communicate with clients【405741767768697†L822-L833】. It exposes the contracts without revealing implementation details. |
| Cargonerds.Application | Implements the application service interfaces defined in the contracts layer. Application services orchestrate domain entities via repositories and domain services, enforce business rules and return DTOs【405741767768697†L836-L846】. |
| Cargonerds.EntityFrameworkCore | Implements data access using Entity Framework Core. It defines the CargonerdsDbContext, maps domain entities to tables and implements the repository interfaces【405741767768697†L848-L855】. |
| Cargonerds.DbMigrator | A console application that applies database migrations and seeds initial data【405741767768697†L859-L884】. It can be run manually or automatically by the AppHost when the system starts. |
| Cargonerds.HttpApi | Hosts the API controllers. ABP auto‑generates controllers for most application services but you can also add custom controllers here【405741767768697†L887-L898】. |
| Cargonerds.HttpApi.Client | Provides strongly typed client proxies for the HTTP APIs【405741767768697†L899-L914】. These proxies can be used by other .NET applications or the Blazor client to call the backend. |
| Cargonerds.AuthServer | Implements an OpenIddict‑based authentication and authorisation server. It issues access tokens to clients and hosts the login UI. The module depends on several ABP Identity and OpenIddict modules and is configured in CargonerdsAuthServerModule.cs. |
| Cargonerds.HttpApi.Host | Hosts the actual backend APIs. It references Cargonerds.HttpApi for the controller definitions and sets up the service defaults (health checks, OpenTelemetry, resilience) via Cargonerds.ServiceDefaults. The host is configured for both local development (using Dockerised resources) and production. |
| Cargonerds.Web.Public | Provides the public facing website built with ASP.NET Core MVC/Razor Pages. It consumes the APIs via the .HttpApi layer and is styled using ABP’s LeptonX theme【405741767768697†L919-L929】. |
| Cargonerds.Blazor | Implements a client‑side Blazor WebAssembly application for internal users. It references .HttpApi.Client to call the backend and uses ABP’s Blazor UI libraries. A separate Cargonerds.Blazor.Client project hosts the WebAssembly files when running in an ASP.NET Core environment. |
| Cargonerds.ServiceDefaults | A utility project that adds default .NET Aspire services to each host. Its AddServiceDefaults extension registers service discovery, resilience policies, health checks and OpenTelemetry instrumentation. It is referenced by all service hosts to ensure consistent configuration. |
| Cargonerds.AppHost | The .NET Aspire project that orchestrates all services and resources. It declares resources such as SQL Server, Redis and RabbitMQ and wires them to projects using fluent extension methods. Running this project spins up the full system locally or provisions equivalent Azure services when deployed. |
Domain example: Books¶
To make the domain more concrete, the main module includes a simple Books
subsystem. The Cargonerds.Domain project defines a Book entity and
repository interface. In the Cargonerds.Application project there is
a BookAppService class that implements an IBookAppService interface
(defined in the contracts layer). This service provides CRUD
operations for books using ABP’s repository abstractions. The
auto‑generated API controllers in the HttpApi project expose these
operations over REST and gRPC.
The same pattern applies to more complex features: the domain layer contains the business objects, the application layer orchestrates them and the HttpApi layer exposes them to clients.
Authentication server¶
The AuthServer project is a specialised ABP host that runs an
OpenIddict server. It depends on ABP’s Identity and OpenIddict
modules (see CargonerdsAuthServerModule.cs) and exposes endpoints
for token issuance, login and consent. It also integrates with
Redis for distributed caching and with Serilog and OpenTelemetry for
logging and tracing. Clients (the Web.Public site, the Blazor
application and the NPM app) authenticate via the AuthServer to obtain
access tokens.
API host and UI projects¶
The HttpApi.Host project is responsible for hosting the backend APIs.
It references the controllers defined in Cargonerds.HttpApi and uses
service defaults for health checks and telemetry. The Web.Public project
contains Razor pages for the public web site and also consumes the APIs.
In tiered deployments the Web.Public project does not directly depend
on the application or EF Core layers【405741767768697†L931-L941】, because all business logic is
accessed via the HTTP APIs. The Blazor and Blazor.Client projects
implement a SPA using Blazor WebAssembly and call the backend via the
HttpApi.Client proxies. An optional NpmApp can also be wired into the
system via the AppHost; this app (for example an Next.js front‑end)
generates its client proxies using the GenerateAbpClientProxies command
defined in the AppHost.
Running the Cargonerds module with .NET Aspire¶
.NET Aspire provides a declarative way to spin up all resources and
services required by the application【798564215460282†L254-L259】. The
Cargonerds.AppHost project defines the distributed application using
fluent API calls in its Program.cs. When you run the AppHost, it:
- Creates infrastructure resources – a SQL Server container, a Redis cache and a RabbitMQ instance. In development these are run as Docker containers; in production they are mapped to Azure SQL, Azure Cache for Redis and Azure Service Bus.
- Starts the services – the DbMigrator (to apply migrations and seed data), AuthServer, HttpApi.Host, Web.Public, Blazor and the optional NPM app. Each service is configured to reference the infrastructure resources and to expose HTTP endpoints.
- Configures dependencies – using custom extension methods (for
example
WithAbpSelfUrl,WithAbpRedisReference,WithAbpRabbitMQReference), the AppHost injects connection strings and configuration into each service. It also registers each service with service discovery and configures health checks.
To run the application locally:
The Aspiration dashboard will open automatically and show all services and resources. You can then browse to the following default URLs:
- AuthServer – http://localhost:5000 (for login and token issuance)
- HttpApi.Host – http://localhost:6000 (REST and gRPC API endpoints)
- Web.Public – http://localhost:7000 (public web site)
- Blazor – http://localhost:8000 (Blazor SPA)
These ports may vary depending on your environment. The Aspire dashboard
displays the actual ports and the health status of each service. If you
modify the code or add new entities, you can run the DbMigrator
project manually with dotnet run in the Cargonerds.DbMigrator folder
to apply migrations and seed data before starting the AppHost.
Localization resources and translations¶
ABP uses localization resources to provide multi‑lingual
user interfaces. The Cargonerds.Domain.Shared project contains a
Localization/Cargonerds folder with JSON files for each supported
culture (for example en.json, de-DE.json, fr.json etc.). These
files define the keys and values used by the UI and error messages.
When you add a new localization key in your code (for example when
throwing a new domain exception), you need to provide translations for
all target languages.
The file translation.options.json in the same folder configures
ResourceTranslator.Cli, a CLI tool that uses the Microsoft
Translator service to automatically generate translations. To translate
new keys:
- Install the
Resourcetranslator.Clitool (for example viadotnet tool install --global Resourcetranslator.Cli). - Add your new keys to the default language file (e.g.
en.json). - Run the translator from the root of the solution:
resourcetranslator translate --options src/Cargonerds.Domain.Shared/translation.options.json --input src/Cargonerds.Domain.Shared/Localization/Cargonerds/en.json --output src/Cargonerds.Domain.Shared/Localization/Cargonerds
The tool reads translation.options.json to determine the target
cultures and writes translated files (e.g. de-DE.json, fr.json).
4. Commit the updated resource files to source control. The ABP
framework will automatically load them at runtime and display the
translations in the UI.
The same pattern applies to the Hub module (see its own
translation.options.json and Localization/Hub folder).
Generating DTOs and mapping with Nextended.CodeGen¶
To reduce boilerplate, this solution uses Nextended.CodeGen, a
source generator that automatically creates Data Transfer Objects (DTOs)
and mapping extension methods based on your domain entities. The
configuration resides in CodeGen.config.json inside each domain
project. For example, the Hub module contains a config file with
Namespace, Suffix, OutputPath and MappingOutputPath settings. When
you build the solution, the generator creates DTO classes in the
Generated folder under the application contracts project and
corresponding mapping extensions in the application project. These
generated files have the .g.cs suffix and should not be edited
manually; instead, modify the domain entities or update the
configuration, rebuild the solution and the generator will update the
DTOs and mappings automatically. This approach ensures that DTOs stay
in sync with the domain model and reduces repetitive coding.
Summary¶
The Cargonerds module demonstrates how to build a layered, modular application using the ABP framework and how to orchestrate it with .NET Aspire. By keeping each concern in its own project and by leveraging Aspire for resource provisioning, the solution remains maintainable and cloud‑ready. The next section of this documentation describes the Hub bounded context, which follows the same patterns as the Cargonerds module but implements its own domain and application services.