api-versioning
API versioning strategies for ASP.NET Core. Covers Asp.Versioning library, URL segment, header, and query string strategies,…
Native AOT, trimming, and single-file publishing for .NET 10: PublishAot, IsAotCompatible analyzers, source-generated JSON/regex/logging/config binding, fixing IL2xxx/IL3xxx trim and AOT warnings, per-RID publishing, and when NOT to use AOT. Load when the user mentions "Native
Claude Code
$ npx -y skills add codewithmukesh/dotnet-claude-kit --skill native-aot --agent claude-code
Codex
$ npx skills add codewithmukesh/dotnet-claude-kit --skill native-aot -a codex -y
Cursor
$ npx skills add codewithmukesh/dotnet-claude-kit --skill native-aot -a cursor -y
Gemini CLI
$ npx skills add codewithmukesh/dotnet-claude-kit --skill native-aot -a gemini-cli -y
GitHub Copilot
$ npx skills add codewithmukesh/dotnet-claude-kit --skill native-aot -a github-copilot -y
OpenCode
$ npx skills add codewithmukesh/dotnet-claude-kit --skill native-aot -a opencode -y
Windsurf
$ npx skills add codewithmukesh/dotnet-claude-kit --skill native-aot -a windsurf -y
name: native-aot description: > Native AOT, trimming, and single-file publishing for .NET 10: PublishAot, IsAotCompatible analyzers, source-generated JSON/regex/logging/config binding, fixing IL2xxx/IL3xxx trim and AOT warnings, per-RID publishing, and when NOT to use AOT. Load when the user mentions "Native AOT", "PublishAot", "trimming", "PublishTrimmed", "single-file", "IL2026", "IL3050", "trim warning", "startup time", "self-contained", or "JsonSerializerContext".
1. **Decide early** — AOT constrains library choice (no runtime reflection or code generation). Adding it to a mature reflection-heavy app is a rewrite. Adding it on day one costs almost nothing. 2. **A trim/AOT warning is a future runtime crash** — IL2xxx (trimming) and IL3xxx (AOT/single-file) warnings mark code that may throw `MissingMethodException` or silently misbehave in the published binary. Treat them as errors and keep the count at zero. 3. **Source generators replace reflection** — JSON, regex, logging, configuration binding, options validation, and MVVM all have generators. They keep the AOT path fast and analyzable. 4. **Test the published artifact, not `dotnet run`** — `dotnet run` uses the JIT and full metadata, so it hides every trimming bug. Smoke-test the binary that `dotnet publish` produces, in CI. 5. **AOT is a trade, not a free upgrade** — You get fast startup, small memory, and no runtime install. You lose dynamic loading, `Reflection.Emit`, and some steady-state throughput from Dynamic PGO. Pick it where those trade-offs pay.
<!-- App (executable) project --> <PropertyGroup> <TargetFramework>net10.0</TargetFramework> <PublishAot>true</PublishAot> <!-- also turns on AOT analyzers during build --> <InvariantGlobalization>true</InvariantGlobalization> <!-- drop ICU if you don't need cultures --> <OptimizationPreference>Size</OptimizationPreference> <!-- or Speed --> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <!-- Every class library the app references --> <PropertyGroup> <IsAotCompatible>true</IsAotCompatible> <!-- implies IsTrimmable + trim/AOT/single-file analyzers --> </PropertyGroup>
dotnet publish -c Release -r linux-x64 # one RID per publish
**Why:** putting `PublishAot` in the project file (not only on the command line) runs the analyzers on every build, so warnings appear while you code. `IsAotCompatible` on libraries surfaces problems at the source instead of in the app. Native AOT needs the platform toolchain (VS "Desktop development with C++" on Windows, `clang` + `zlib` dev packages on Linux, Xcode CLI tools on macOS). Build each OS on that OS in a CI matrix. A Linux binary runs only on the same or newer distro version it was built on.
public sealed record OrderDto(Guid Id, string Customer, decimal Total, DateTimeOffset CreatedAt); [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] [JsonSerializable(typeof(OrderDto))] [JsonSerializable(typeof(List<OrderDto>))] internal sealed partial class AppJsonContext : JsonSerializerContext; // Usage — pass the generated JsonTypeInfo, never a bare Type var json = JsonSerializer.Serialize(order, AppJsonContext.Default.OrderDto); var orders = await JsonSerializer.DeserializeAsync(stream, AppJsonContext.Default.ListOrderDto, ct);
// ASP.NET Core minimal APIs: register the context once
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.ConfigureHttpJsonOptions(o =>
o.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default));**Why:** reflection-based `System.Text.Json` is disabled in trimmed/AOT apps. The generated metadata is also faster on the JIT. Register every type that crosses the wire, including collection shapes (`List<OrderDto>`). `CreateSlimBuilder` leaves out non-AOT-friendly defaults. The minimal API Request Delegate Generator turns on automatically with `PublishAot`.
internal static partial class Patterns
{
[GeneratedRegex(@"^ORD-\d{6}$", RegexOptions.CultureInvariant)]
internal static partial Regex OrderNumber { get; }
}
internal static partial class Log
{
[LoggerMessage(Level = LogLevel.Information, Message = "Imported {Count} orders in {ElapsedMs} ms")]
internal static partial void Imported(ILogger logger, int count, long elapsedMs);
}
[OptionsValidator]
internal sealed partial class ImportOptionsValidator : IValidateOptions<ImportOptions>;
public sealed class ImportOptions
{
[Range(1, 10_000)] public int BatchSize { get; set; } = 500;
}<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
**Why:** `[GeneratedRegex]` emits matching code at compile time (no `RegexOptions.Compiled`, which needs runtime IL emit). `[LoggerMessage]` avoids boxing and parsing the template on every call. The configuration binding generator replaces the reflection inside `Bind`/`Get<T>`/`Configure<T>`. `[OptionsValidator]` replaces reflection-based data-annotation validation.
// Propagate the requirement to callers instead of hiding it
[RequiresUnreferencedCode("Loads plugin types by name; not trim-safe.")]
[RequiresDynamicCode("Creates generic types at runtime.")]
public static object CreatePlugin(string typeName) => Activator.CreateInstance(Type.GetType(typeName)!)!;
// Or tell the trimmer exactly what to keep
public static T Create<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] T>()
where T : new() => new();
public static object CreateFrom(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) =>
Activator.CreateInstance(type)!;*
API versioning strategies for ASP.NET Core. Covers Asp.Versioning library, URL segment, header, and query string strategies,…
Architecture conformance check: verifies an existing codebase against its declared architecture (VSA, Clean Architecture, DDD,…
Architecture selection advisor for .NET applications. Asks structured questions about domain complexity, team size, system…
.NET Aspire for cloud-native orchestration. Covers AppHost configuration, service defaults, resource configuration, service…
Authentication and authorization for ASP.NET Core. Covers JWT bearer tokens, OpenID Connect, ASP.NET Identity, authorization…
Avalonia UI 12 for cross-platform .NET desktop apps: compiled bindings (x:DataType, on by default in 12),…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.