Skip to content

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:

  1. 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.
  2. 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.
  3. 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:

cd src/Cargonerds.AppHost
dotnet run

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:

  1. Install the Resourcetranslator.Cli tool (for example via dotnet tool install --global Resourcetranslator.Cli).
  2. Add your new keys to the default language file (e.g. en.json).
  3. 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.