.NET
Overview
.NET is Microsoft's open-source, cross-platform framework for building web APIs, cloud services, desktop applications, mobile apps, games, IoT, and AI/ML solutions. The modern .NET platform (6+) unifies what were formerly separate runtimes (.NET Framework, .NET Core, Mono) into a single SDK. C# is the primary language, with F# for functional programming. The ecosystem spans 400,000+ NuGet packages, first-party Azure integration, and tooling through Visual Studio, VS Code, and JetBrains Rider.
Knowledge Map
dotnet/
├── ai/ # ML.NET, ONNX, Azure AI, Microsoft.Extensions.AI, agents (A2A, MCP)
├── cli/ # Spectre.Console, CliWrap, command-line cheatsheet
├── cloud/ # Aspire, Azure Functions, Dapr, Orleans, service discovery
├── configuration/ # Extensions.Configuration, caching, feature flags, OpenFeature
├── data/ # EF Core, Dapper, Redis, Lucene.NET, FluentStorage
├── dependency-injection/ # Extensions.DI, Generic Host, Spring.NET
├── documentation/ # OpenAPI / Swagger
├── eventing/ # MediatR, MassTransit, NServiceBus, Rebus, Wolverine, Brighter, Akka.NET
├── functional/ # F#, Language.Ext, FParsec, Optional, pidgin
├── general/ # Humanizer, ImageSharp, NodaTime, Stateless, worker services, cheatsheet
├── localization/ # i18n, resource-based localization, MessageFormat
├── logging/ # Serilog, NLog, Extensions.Logging
├── mapping/ # AutoMapper, Mapperly
├── networking/ # gRPC, DotNetty, MimeKit, System.IO.Pipelines, Twilio
├── observability/ # OTLP logging, OpenTelemetry conventions
├── project-system/ # MSBuild/csproj, Roslyn analyzers, source generators, EditorConfig, Fody
├── reactive/ # Rx.NET, System.Threading.Channels, DynamicData, IAsyncEnumerable
├── resilience/ # Polly, Extensions.Resilience
├── security/ # ASP.NET Identity, cryptography, authorization (Topaz, Enforcer)
├── serialization/ # Protobuf-net, Bond, Hyperion, FluentSerializer
├── testing/ # Testcontainers, Moq, AutoFixture, Pact, Reqnroll, Playwright
├── ui/ # MAUI, Avalonia, Blazor, Uno Platform, Blazorise, MonoGame, Unity
├── validation/ # FluentValidation, Validot, Parse Don't Validate, CommunityToolkit.Guard
└── web/ # ASP.NET Core, SignalR, YARP, Ocelot, GraphQL, Refit, Orchard CMS
Choosing Guide
| Problem |
Sub-Skill |
Notes |
| Build a web API or microservice |
web/aspnet-core |
Minimal APIs for simple endpoints, controllers for complex APIs |
| Add real-time push to a web app |
web/signalr |
WebSocket abstraction with automatic fallback to SSE/long-polling |
| Reverse proxy or API gateway |
web/yarp or web/ocelot |
YARP for high-perf programmatic proxy, Ocelot for config-driven gateway |
| GraphQL API |
web/graphql |
Hot Chocolate server with filtering, sorting, subscriptions |
| Access a relational database |
data/entity-framework-core |
Full ORM with migrations, change tracking, LINQ queries |
| Lightweight SQL queries |
data/dapper |
Micro-ORM, raw SQL with object mapping, best for read-heavy paths |
| Distributed cache |
data/redis or configuration/extensions-caching |
Redis for shared cache, IMemoryCache/IDistributedCache for local/hybrid |
| Event-driven / CQRS architecture |
eventing/mediatr |
In-process mediator; combine with eventing/masstransit for cross-service |
| Message bus (RabbitMQ, Kafka, Azure SB) |
eventing/masstransit |
Abstraction over transports with sagas, retries, and outbox pattern |
| Build a .NET Aspire app |
cloud/aspire |
Orchestrate multi-project apps with built-in service discovery and telemetry |
| Serverless functions |
cloud/azure-functions |
Isolated worker model for Azure Functions with DI and middleware |
| Resilience (retries, circuit breakers) |
resilience/polly |
Configurable policies; use resilience/extensions-resilience for DI integration |
| Structured logging |
logging/serilog |
Sinks for Console, Seq, Elasticsearch, Application Insights |
| Object mapping |
mapping/mapperly |
Source-generator-based mapper (zero reflection, compile-time safe) |
| Input validation |
validation/fluent-validations |
Fluent rules with DI integration and ASP.NET Core auto-validation |
| Integration testing with real DBs |
testing/testcontainers |
Docker-based throwaway containers for Postgres, SQL Server, Redis |
| Mocking in unit tests |
testing/moq |
Proxy-based mocking with LINQ setup expressions |
| Contract testing |
testing/pact |
Consumer-driven contract tests for microservice boundaries |
| BDD / Gherkin |
testing/reqnroll |
SpecFlow successor — Given/When/Then with .NET 8+ support |
| Cross-platform desktop app |
ui/avalonia |
XAML-based UI for Windows, macOS, Linux, iOS, Android, WebAssembly |
| Mobile + desktop from one codebase |
ui/maui |
Microsoft's official cross-platform UI framework (.NET 8+) |
| Interactive web UI in C# |
ui/blazor |
Server-side or WebAssembly rendering with Razor components |
| Functional programming in C# |
functional/language-ext |
Immutable collections, Option/Either monads, pattern matching extensions |
| F# language guidance |
functional/fsharp |
Type providers, computation expressions, pipelines, domain modeling |
| AI/ML inference |
ai/microsoft-extensions-ai |
Unified abstraction for OpenAI, Azure AI, Ollama, and custom providers |
| Train ML models in .NET |
ai/mlnet |
AutoML, classification, regression, anomaly detection, recommendation |
| Build a CLI tool |
cli/spectre-console |
Rich terminal UI with tables, trees, progress bars, prompts |
| Source generators |
project-system/generators-cheatsheet |
Compile-time code generation with Roslyn incremental generators |
| Roslyn code analysis |
project-system/roslyn-analyzers |
Custom analyzers and code fixes for enforcing team conventions |
.NET Version Landscape
| Version |
Release |
Support |
Key Features |
| .NET 6 |
Nov 2021 |
LTS (ended Nov 2024) |
Minimal APIs, hot reload, DateOnly/TimeOnly, HTTP/3, AOT groundwork |
| .NET 7 |
Nov 2022 |
STS (ended May 2024) |
Native AOT for console apps, rate limiting middleware, output caching |
| .NET 8 |
Nov 2023 |
LTS (until Nov 2026) |
.NET Aspire, FrozenDictionary, keyed DI, native AOT for web, TimeProvider |
| .NET 9 |
Nov 2024 |
STS (until May 2026) |
System.Threading.Lock, LINQ CountBy/AggregateBy, TypedResults improvements |
Choosing a Version
- Starting a new project? Use .NET 8 (LTS) for stability, or .NET 9 for latest features.
- In production with .NET 6? Plan migration to .NET 8 — .NET 6 support has ended.
- Need native AOT? .NET 8+ supports AOT for ASP.NET Core minimal APIs and gRPC.
- Using Aspire for orchestration? Requires .NET 8+.
C# Quick Reference
Modern C# Features (10-13)
// Global usings (C# 10) — reduce boilerplate across files
global using System.Text.Json;
global using Microsoft.Extensions.Logging;
// File-scoped namespaces (C# 10)
namespace MyApp.Services;
// Records with positional syntax — immutable data types
public record OrderPlaced(Guid OrderId, string CustomerId, decimal Total, DateTime PlacedAt);
// Primary constructors (C# 12) — DI without field ceremony
public class OrderService(IOrderRepository repo, ILogger<OrderService> logger)
{
public async Task<Order> GetAsync(Guid id)
{
logger.LogInformation("Fetching order {OrderId}", id);
return await repo.FindAsync(id) ?? throw new NotFoundException(id);
}
}
// Collection expressions (C# 12)
int[] numbers = [1, 2, 3, 4, 5];
List<string> names = ["Alice", "Bob", "Charlie"];
ReadOnlySpan<byte> header = [0x48, 0x54, 0x54, 0x50];
// Pattern matching with list patterns (C# 11)
string Describe(int[] values) => values switch
{
[] => "empty",
[var single] => $"one item: {single}",
[var first, .., var last] => $"from {first} to {last}",
};
// Raw string literals (C# 11) — no escaping needed
var json = """
{
"name": "Widget",
"price": 29.99,
"tags": ["electronics", "sale"]
}
""";
// Required members (C# 11)
public class Config
{
public required string ConnectionString { get; init; }
public required int MaxRetries { get; init; }
public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(30);
}
// Switch expressions with property patterns
decimal CalculateDiscount(Order order) => order switch
{
{ Total: > 1000, Customer.IsPremium: true } => order.Total * 0.15m,
{ Total: > 500 } => order.Total * 0.10m,
{ Customer.IsPremium: true } => order.Total * 0.05m,
_ => 0m,
};
Key NuGet Package Categories
| Category |
Go-To Packages |
When to Use |
| Web Framework |
ASP.NET Core (built-in) |
REST APIs, Razor Pages, Blazor, gRPC |
| ORM |
EF Core, Dapper |
EF Core for full ORM, Dapper for raw SQL performance |
| Validation |
FluentValidation, Validot |
Fluent rule definitions, DI-friendly, auto-wire with ASP.NET |
| Mapping |
Mapperly, AutoMapper |
Mapperly for source-gen (zero reflection), AutoMapper for convention-based |
| Serialization |
System.Text.Json, Protobuf-net |
STJ for JSON (built-in), Protobuf for binary/gRPC |
| Logging |
Serilog, NLog |
Structured logging with sinks for Seq, Elastic, AppInsights |
| Testing |
xUnit, Moq, AutoFixture, Testcontainers |
xUnit as test framework, Moq for mocks, Testcontainers for integration |
| Resilience |
Polly, Extensions.Resilience |
Retry, circuit breaker, timeout, rate limiter policies |
| Messaging |
MassTransit, MediatR, NServiceBus |
MassTransit for bus abstraction, MediatR for in-process CQRS |
| DI |
Extensions.DI (built-in) |
Constructor injection, scoped/transient/singleton lifetimes |
| Caching |
Extensions.Caching, StackExchange.Redis |
IMemoryCache for local, IDistributedCache for Redis/SQL |
| HTTP Client |
Refit, RestSharp |
Refit for interface-defined clients, RestSharp for simpler REST calls |
| CLI |
Spectre.Console, System.CommandLine |
Rich terminal UIs, argument parsing, help generation |
| Cloud |
.NET Aspire, Azure.Identity |
Aspire for orchestration, Azure.Identity for managed identity auth |
Best Practices
Use the latest LTS release (.NET 8) for production workloads. LTS releases receive 3 years of security patches and bug fixes.
Enable nullable reference types (<Nullable>enable</Nullable>) in every project. This catches null-reference bugs at compile time:
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
Use IOptions<T> pattern for configuration instead of reading values directly. This provides validation, reload support, and testability:
public class SmtpOptions
{
public const string Section = "Smtp";
public required string Host { get; init; }
public int Port { get; init; } = 587;
public required string FromAddress { get; init; }
}
// In Program.cs
builder.Services.AddOptions<SmtpOptions>()
.BindConfiguration(SmtpOptions.Section)
.ValidateDataAnnotations()
.ValidateOnStart();
Prefer records for data transfer objects and events. Records provide value equality, immutability, and concise syntax. Use record class for heap-allocated (default) and record struct for stack-allocated small types.
Use primary constructors for DI in services and controllers (C# 12). This eliminates boilerplate private readonly fields while keeping constructor injection.
Avoid async void — it swallows exceptions. Always return Task or ValueTask from async methods. The only exception is event handlers.
Use CancellationToken everywhere — pass it through all async call chains so requests can be cancelled cleanly when clients disconnect:
app.MapGet("/orders/{id}", async (Guid id, IOrderRepository repo, CancellationToken ct) =>
await repo.FindAsync(id, ct) is { } order
? Results.Ok(order)
: Results.NotFound());
Register services with the correct lifetime — Singleton for stateless/thread-safe services, Scoped for per-request state (EF DbContext), Transient for lightweight stateless operations. Never inject Scoped into Singleton.
Use source generators over reflection where available (Mapperly, System.Text.Json source gen, Roslyn analyzers). Source generators run at compile time, eliminate reflection costs, and are compatible with Native AOT.
Structure solutions with clear project boundaries — separate API host, domain logic, infrastructure, and tests into distinct projects. Use <ProjectReference> and enforce dependency direction (domain has no external references).
1---2name: dotnet3description: Use when working with C#, F#, .NET libraries, ASP.NET Core, Blazor, Entity Framework Core, and the broader .NET ecosystem. USE FOR: .NET language features, choosing libraries and frameworks, project structure, package selection, architecture decisions DO NOT USE FOR: specific library configuration details (use the sub-skills: web, data, testing, eventing, cloud, etc.)4license: MIT5---67# .NET89## Overview1011.NET is Microsoft's open-source, cross-platform framework for building web APIs, cloud services, desktop applications, mobile apps, games, IoT, and AI/ML solutions. The modern .NET platform (6+) unifies what were formerly separate runtimes (.NET Framework, .NET Core, Mono) into a single SDK. C# is the primary language, with F# for functional programming. The ecosystem spans 400,000+ NuGet packages, first-party Azure integration, and tooling through Visual Studio, VS Code, and JetBrains Rider.1213## Knowledge Map1415```16dotnet/17├── ai/ # ML.NET, ONNX, Azure AI, Microsoft.Extensions.AI, agents (A2A, MCP)18├── cli/ # Spectre.Console, CliWrap, command-line cheatsheet19├── cloud/ # Aspire, Azure Functions, Dapr, Orleans, service discovery20├── configuration/ # Extensions.Configuration, caching, feature flags, OpenFeature21├── data/ # EF Core, Dapper, Redis, Lucene.NET, FluentStorage22├── dependency-injection/ # Extensions.DI, Generic Host, Spring.NET23├── documentation/ # OpenAPI / Swagger24├── eventing/ # MediatR, MassTransit, NServiceBus, Rebus, Wolverine, Brighter, Akka.NET25├── functional/ # F#, Language.Ext, FParsec, Optional, pidgin26├── general/ # Humanizer, ImageSharp, NodaTime, Stateless, worker services, cheatsheet27├── localization/ # i18n, resource-based localization, MessageFormat28├── logging/ # Serilog, NLog, Extensions.Logging29├── mapping/ # AutoMapper, Mapperly30├── networking/ # gRPC, DotNetty, MimeKit, System.IO.Pipelines, Twilio31├── observability/ # OTLP logging, OpenTelemetry conventions32├── project-system/ # MSBuild/csproj, Roslyn analyzers, source generators, EditorConfig, Fody33├── reactive/ # Rx.NET, System.Threading.Channels, DynamicData, IAsyncEnumerable34├── resilience/ # Polly, Extensions.Resilience35├── security/ # ASP.NET Identity, cryptography, authorization (Topaz, Enforcer)36├── serialization/ # Protobuf-net, Bond, Hyperion, FluentSerializer37├── testing/ # Testcontainers, Moq, AutoFixture, Pact, Reqnroll, Playwright38├── ui/ # MAUI, Avalonia, Blazor, Uno Platform, Blazorise, MonoGame, Unity39├── validation/ # FluentValidation, Validot, Parse Don't Validate, CommunityToolkit.Guard40└── web/ # ASP.NET Core, SignalR, YARP, Ocelot, GraphQL, Refit, Orchard CMS41```4243## Choosing Guide4445| Problem | Sub-Skill | Notes |46|---------|-----------|-------|47| Build a web API or microservice | `web/aspnet-core` | Minimal APIs for simple endpoints, controllers for complex APIs |48| Add real-time push to a web app | `web/signalr` | WebSocket abstraction with automatic fallback to SSE/long-polling |49| Reverse proxy or API gateway | `web/yarp` or `web/ocelot` | YARP for high-perf programmatic proxy, Ocelot for config-driven gateway |50| GraphQL API | `web/graphql` | Hot Chocolate server with filtering, sorting, subscriptions |51| Access a relational database | `data/entity-framework-core` | Full ORM with migrations, change tracking, LINQ queries |52| Lightweight SQL queries | `data/dapper` | Micro-ORM, raw SQL with object mapping, best for read-heavy paths |53| Distributed cache | `data/redis` or `configuration/extensions-caching` | Redis for shared cache, IMemoryCache/IDistributedCache for local/hybrid |54| Event-driven / CQRS architecture | `eventing/mediatr` | In-process mediator; combine with `eventing/masstransit` for cross-service |55| Message bus (RabbitMQ, Kafka, Azure SB) | `eventing/masstransit` | Abstraction over transports with sagas, retries, and outbox pattern |56| Build a .NET Aspire app | `cloud/aspire` | Orchestrate multi-project apps with built-in service discovery and telemetry |57| Serverless functions | `cloud/azure-functions` | Isolated worker model for Azure Functions with DI and middleware |58| Resilience (retries, circuit breakers) | `resilience/polly` | Configurable policies; use `resilience/extensions-resilience` for DI integration |59| Structured logging | `logging/serilog` | Sinks for Console, Seq, Elasticsearch, Application Insights |60| Object mapping | `mapping/mapperly` | Source-generator-based mapper (zero reflection, compile-time safe) |61| Input validation | `validation/fluent-validations` | Fluent rules with DI integration and ASP.NET Core auto-validation |62| Integration testing with real DBs | `testing/testcontainers` | Docker-based throwaway containers for Postgres, SQL Server, Redis |63| Mocking in unit tests | `testing/moq` | Proxy-based mocking with LINQ setup expressions |64| Contract testing | `testing/pact` | Consumer-driven contract tests for microservice boundaries |65| BDD / Gherkin | `testing/reqnroll` | SpecFlow successor — Given/When/Then with .NET 8+ support |66| Cross-platform desktop app | `ui/avalonia` | XAML-based UI for Windows, macOS, Linux, iOS, Android, WebAssembly |67| Mobile + desktop from one codebase | `ui/maui` | Microsoft's official cross-platform UI framework (.NET 8+) |68| Interactive web UI in C# | `ui/blazor` | Server-side or WebAssembly rendering with Razor components |69| Functional programming in C# | `functional/language-ext` | Immutable collections, Option/Either monads, pattern matching extensions |70| F# language guidance | `functional/fsharp` | Type providers, computation expressions, pipelines, domain modeling |71| AI/ML inference | `ai/microsoft-extensions-ai` | Unified abstraction for OpenAI, Azure AI, Ollama, and custom providers |72| Train ML models in .NET | `ai/mlnet` | AutoML, classification, regression, anomaly detection, recommendation |73| Build a CLI tool | `cli/spectre-console` | Rich terminal UI with tables, trees, progress bars, prompts |74| Source generators | `project-system/generators-cheatsheet` | Compile-time code generation with Roslyn incremental generators |75| Roslyn code analysis | `project-system/roslyn-analyzers` | Custom analyzers and code fixes for enforcing team conventions |7677## .NET Version Landscape7879| Version | Release | Support | Key Features |80|---------|---------|---------|-------------|81| **.NET 6** | Nov 2021 | LTS (ended Nov 2024) | Minimal APIs, hot reload, `DateOnly`/`TimeOnly`, HTTP/3, AOT groundwork |82| **.NET 7** | Nov 2022 | STS (ended May 2024) | Native AOT for console apps, rate limiting middleware, output caching |83| **.NET 8** | Nov 2023 | LTS (until Nov 2026) | .NET Aspire, `FrozenDictionary`, keyed DI, native AOT for web, `TimeProvider` |84| **.NET 9** | Nov 2024 | STS (until May 2026) | `System.Threading.Lock`, LINQ `CountBy`/`AggregateBy`, `TypedResults` improvements |8586### Choosing a Version8788- **Starting a new project?** Use .NET 8 (LTS) for stability, or .NET 9 for latest features.89- **In production with .NET 6?** Plan migration to .NET 8 — .NET 6 support has ended.90- **Need native AOT?** .NET 8+ supports AOT for ASP.NET Core minimal APIs and gRPC.91- **Using Aspire for orchestration?** Requires .NET 8+.9293## C# Quick Reference9495### Modern C# Features (10-13)9697```csharp98// Global usings (C# 10) — reduce boilerplate across files99global using System.Text.Json;100global using Microsoft.Extensions.Logging;101102// File-scoped namespaces (C# 10)103namespace MyApp.Services;104105// Records with positional syntax — immutable data types106public record OrderPlaced(Guid OrderId, string CustomerId, decimal Total, DateTime PlacedAt);107108// Primary constructors (C# 12) — DI without field ceremony109public class OrderService(IOrderRepository repo, ILogger<OrderService> logger)110{111 public async Task<Order> GetAsync(Guid id)112 {113 logger.LogInformation("Fetching order {OrderId}", id);114 return await repo.FindAsync(id) ?? throw new NotFoundException(id);115 }116}117118// Collection expressions (C# 12)119int[] numbers = [1, 2, 3, 4, 5];120List<string> names = ["Alice", "Bob", "Charlie"];121ReadOnlySpan<byte> header = [0x48, 0x54, 0x54, 0x50];122123// Pattern matching with list patterns (C# 11)124string Describe(int[] values) => values switch125{126 [] => "empty",127 [var single] => $"one item: {single}",128 [var first, .., var last] => $"from {first} to {last}",129};130131// Raw string literals (C# 11) — no escaping needed132var json = """133 {134 "name": "Widget",135 "price": 29.99,136 "tags": ["electronics", "sale"]137 }138 """;139140// Required members (C# 11)141public class Config142{143 public required string ConnectionString { get; init; }144 public required int MaxRetries { get; init; }145 public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(30);146}147148// Switch expressions with property patterns149decimal CalculateDiscount(Order order) => order switch150{151 { Total: > 1000, Customer.IsPremium: true } => order.Total * 0.15m,152 { Total: > 500 } => order.Total * 0.10m,153 { Customer.IsPremium: true } => order.Total * 0.05m,154 _ => 0m,155};156```157158### Key NuGet Package Categories159160| Category | Go-To Packages | When to Use |161|----------|---------------|-------------|162| **Web Framework** | ASP.NET Core (built-in) | REST APIs, Razor Pages, Blazor, gRPC |163| **ORM** | EF Core, Dapper | EF Core for full ORM, Dapper for raw SQL performance |164| **Validation** | FluentValidation, Validot | Fluent rule definitions, DI-friendly, auto-wire with ASP.NET |165| **Mapping** | Mapperly, AutoMapper | Mapperly for source-gen (zero reflection), AutoMapper for convention-based |166| **Serialization** | System.Text.Json, Protobuf-net | STJ for JSON (built-in), Protobuf for binary/gRPC |167| **Logging** | Serilog, NLog | Structured logging with sinks for Seq, Elastic, AppInsights |168| **Testing** | xUnit, Moq, AutoFixture, Testcontainers | xUnit as test framework, Moq for mocks, Testcontainers for integration |169| **Resilience** | Polly, Extensions.Resilience | Retry, circuit breaker, timeout, rate limiter policies |170| **Messaging** | MassTransit, MediatR, NServiceBus | MassTransit for bus abstraction, MediatR for in-process CQRS |171| **DI** | Extensions.DI (built-in) | Constructor injection, scoped/transient/singleton lifetimes |172| **Caching** | Extensions.Caching, StackExchange.Redis | IMemoryCache for local, IDistributedCache for Redis/SQL |173| **HTTP Client** | Refit, RestSharp | Refit for interface-defined clients, RestSharp for simpler REST calls |174| **CLI** | Spectre.Console, System.CommandLine | Rich terminal UIs, argument parsing, help generation |175| **Cloud** | .NET Aspire, Azure.Identity | Aspire for orchestration, Azure.Identity for managed identity auth |176177## Best Practices1781791. **Use the latest LTS release** (.NET 8) for production workloads. LTS releases receive 3 years of security patches and bug fixes.1801812. **Enable nullable reference types** (`<Nullable>enable</Nullable>`) in every project. This catches null-reference bugs at compile time:182 ```xml183 <PropertyGroup>184 <TargetFramework>net8.0</TargetFramework>185 <Nullable>enable</Nullable>186 <ImplicitUsings>enable</ImplicitUsings>187 </PropertyGroup>188 ```1891903. **Use `IOptions<T>` pattern** for configuration instead of reading values directly. This provides validation, reload support, and testability:191 ```csharp192 public class SmtpOptions193 {194 public const string Section = "Smtp";195 public required string Host { get; init; }196 public int Port { get; init; } = 587;197 public required string FromAddress { get; init; }198 }199200 // In Program.cs201 builder.Services.AddOptions<SmtpOptions>()202 .BindConfiguration(SmtpOptions.Section)203 .ValidateDataAnnotations()204 .ValidateOnStart();205 ```2062074. **Prefer records for data transfer objects and events**. Records provide value equality, immutability, and concise syntax. Use `record class` for heap-allocated (default) and `record struct` for stack-allocated small types.2082095. **Use primary constructors for DI** in services and controllers (C# 12). This eliminates boilerplate `private readonly` fields while keeping constructor injection.2102116. **Avoid `async void`** — it swallows exceptions. Always return `Task` or `ValueTask` from async methods. The only exception is event handlers.2122137. **Use `CancellationToken` everywhere** — pass it through all async call chains so requests can be cancelled cleanly when clients disconnect:214 ```csharp215 app.MapGet("/orders/{id}", async (Guid id, IOrderRepository repo, CancellationToken ct) =>216 await repo.FindAsync(id, ct) is { } order217 ? Results.Ok(order)218 : Results.NotFound());219 ```2202218. **Register services with the correct lifetime** — `Singleton` for stateless/thread-safe services, `Scoped` for per-request state (EF DbContext), `Transient` for lightweight stateless operations. Never inject Scoped into Singleton.2222239. **Use source generators over reflection** where available (Mapperly, System.Text.Json source gen, Roslyn analyzers). Source generators run at compile time, eliminate reflection costs, and are compatible with Native AOT.22422510. **Structure solutions with clear project boundaries** — separate API host, domain logic, infrastructure, and tests into distinct projects. Use `<ProjectReference>` and enforce dependency direction (domain has no external references).