Installation
Prerequisites
Section titled “Prerequisites”- .NET 10 SDK or later (C# 14 support required)
- An IDE with Roslyn / source-generator support: Rider, Visual Studio 2022+, or VS Code with the C# Dev Kit
One-minute quick start
Section titled “One-minute quick start”1. Create a project
Section titled “1. Create a project”dotnet new webapi -n MyServicecd MyService2. Add the Pragmatic NuGets you need
Section titled “2. Add the Pragmatic NuGets you need”The simplest starting point is a Web API with actions, endpoints, and EF Core persistence:
# Composition host (required — ties everything together)dotnet add package Pragmatic.Composition.Host --version 0.8.0-preview.*
# Domain actions + HTTP endpointsdotnet add package Pragmatic.Actions --version 0.8.0-preview.*dotnet add package Pragmatic.Endpoints --version 0.8.0-preview.*
# Persistence (pick EFCore for relational)dotnet add package Pragmatic.Persistence.EFCore --version 0.8.0-preview.*
# Validationdotnet add package Pragmatic.Validation --version 0.8.0-preview.*
# The unified source generator (runs at build time)dotnet add package Pragmatic.SourceGenerator --version 0.8.0-preview.*Each NuGet carries its own analyzer/generator references. Pragmatic.SourceGenerator is the one unified generator — you add it once and it activates the features it detects in the compilation (see Feature Detection).
3. Boot the host
Section titled “3. Boot the host”Program.cs:
using Pragmatic.Composition.Hosting;
await PragmaticApp.RunAsync(args, app =>{ // All Use*() calls are optional — each module ships a working default. // Add strategy calls as you need specific behaviour.});That’s it. dotnet run starts the host; endpoints discovered at compile time are already mapped.
4. Write your first domain action
Section titled “4. Write your first domain action”using Pragmatic.Actions.Abstractions;using Pragmatic.Actions.Attributes;using Pragmatic.Endpoints;using Pragmatic.Endpoints.Attributes;using Pragmatic.Result;using Pragmatic.Validation.Attributes;
[DomainAction][Endpoint(HttpVerb.Post, "/greet")][Validate]public partial class Greet : DomainAction<string>{ [Required, MinLength(1)] public required string Name { get; init; }
public override Task<Result<string, IError>> Execute(CancellationToken ct = default) => Task.FromResult<Result<string, IError>>($"Hello, {Name}!");}Build and send a request:
curl -X POST http://localhost:5000/greet -H 'Content-Type: application/json' -d '{"Name":"Alice"}'# "Hello, Alice!"No manual endpoint registration, no DI ceremony, no validator wiring.
Package families
Section titled “Package families”Pragmatic ships 40 NuGets. The families you likely need:
| Family | Packages | When |
|---|---|---|
| Foundation | Pragmatic.Result, Pragmatic.Ensure, Pragmatic.Abstractions | Always (transitive via most modules) |
| Core | Pragmatic.Actions, Pragmatic.Endpoints, Pragmatic.Composition.Host, Pragmatic.Events | Building a service with a domain |
| Persistence | Pragmatic.Persistence.EFCore, Pragmatic.Migrations | Relational database |
| Messaging | Pragmatic.Messaging, Pragmatic.Messaging.EFCore (outbox), .Channels, .RabbitMQ | Async messaging |
| Identity & Auth | Pragmatic.Identity, Pragmatic.Identity.Local, Pragmatic.Authorization | User identity and permissions |
| Observability | Pragmatic.Logging, Pragmatic.Resilience | Production hardening |
| Documents | Pragmatic.Documents.Pdf, .Docx, .Xlsx, .Csv | Generating documents |
| Medium Blocks | Pragmatic.Comments, Pragmatic.Tags, Pragmatic.Attachments | Entity traits (opt-in) |
See the module catalogue in the sidebar for the full list, each with its own Overview page, Concepts, Getting Started, and API reference.
Central package management (recommended)
Section titled “Central package management (recommended)”For multi-project solutions, use Directory.Packages.props to pin versions once:
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> </PropertyGroup> <ItemGroup> <PackageVersion Include="Pragmatic.Composition.Host" Version="0.8.0-preview.*" /> <PackageVersion Include="Pragmatic.Actions" Version="0.8.0-preview.*" /> <PackageVersion Include="Pragmatic.Endpoints" Version="0.8.0-preview.*" /> <PackageVersion Include="Pragmatic.Persistence.EFCore" Version="0.8.0-preview.*" /> <PackageVersion Include="Pragmatic.Validation" Version="0.8.0-preview.*" /> <PackageVersion Include="Pragmatic.SourceGenerator" Version="0.8.0-preview.*" /> </ItemGroup></Project>Then each .csproj references without versions:
<ItemGroup> <PackageReference Include="Pragmatic.Composition.Host" /> <PackageReference Include="Pragmatic.Actions" /> ...</ItemGroup>Inspecting the generated code
Section titled “Inspecting the generated code”To see what the generator produces:
<PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)/Generated</CompilerGeneratedFilesOutputPath></PropertyGroup>After dotnet build, you’ll find:
obj/Debug/net10.0/Generated/└── Pragmatic.SourceGenerator/ └── Pragmatic.SourceGenerator.PragmaticSourceGenerator/ ├── Greet.Invoker.g.cs ├── _Boundary.Default.Endpoints.g.cs ├── _Infra.Actions.Registration.g.cs └── …Read them. They are standard C#, formatted and commented.
Troubleshooting
Section titled “Troubleshooting”Nothing is generated after dotnet build. You likely didn’t reference Pragmatic.SourceGenerator. It is the analyzer package — without it, no generation runs. Verify with dotnet list package | grep SourceGenerator.
IDE doesn’t see generated types. The IDE caches analyzer output. In Rider: File → Invalidate Caches / Clear Cache. In VS: restart. A full dotnet build almost always fixes it.
PRAG#### errors at build time. The generator detected a misuse. See the Diagnostics reference for the meaning and fix.
“Module A is active but I didn’t add it.” Pragmatic meta-packages bring transitive dependencies. Check dotnet list package --include-transitive. Pragmatic modules only activate if a marker type is reachable — if you see generation you didn’t ask for, a reference is pulling it in.
Next steps
Section titled “Next steps”- Architecture — how the 3-tier model fits together
- Pick a module from the sidebar and read its Overview / Concepts
- Showcase — full reference app composing 30+ modules
- Samples — every module has a runnable
samples/project