How AI Agents Assist with ASP.NET Core Development Using dotnet-aspnetcore Skills
AI agents use the markdown-based skill definitions in the dotnet/skills repository to generate secure, standards-compliant ASP.NET Core code by following Microsoft-approved architectural patterns, validation checklists, and concrete implementation examples.
The dotnet-aspnetcore plugin within the dotnet/skills repository provides structured skill definitions that transform AI agents from guesswork-based assistants into knowledge-driven code generators. These skills are self-contained Markdown files living under plugins/dotnet-aspnetcore/skills/, enabling agents to reason about project requirements and emit production-ready minimal APIs, Web API endpoints, and observability configurations that align with current .NET best practices.
How AI Agents Use dotnet-aspnetcore Skill Definitions
The agent workflow follows a deterministic six-step process defined by the skill architecture. Each skill file contains "When to Use" contexts, "Workflow" steps, "Common Mistakes" to avoid, and concrete code snippets that guide the agent's reasoning.
Step 1: Identify the Problem and Select the Skill
When a developer requests a feature such as "file upload in a minimal API" or "create a new Web API endpoint," the agent parses the request and extracts the relevant skill identifier. For file handling scenarios, the agent selects minimal-api-file-upload; for standard REST APIs, it selects dotnet-webapi.
Step 2: Load the Skill Description from Markdown
The agent reads the skill's SKILL.md file to ingest the architectural requirements. Key files include:
plugins/dotnet-aspnetcore/skills/minimal-api-file-upload/SKILL.md– Defines secure upload patterns with anti-forgery and size limits.plugins/dotnet-aspnetcore/skills/dotnet-webapi/SKILL.md– Covers DTO conventions,TypedResultsusage, and OpenAPI configuration.plugins/dotnet-aspnetcore/skills/configuring-opentelemetry-dotnet/SKILL.md– Specifies tracing and exporter pipeline setup.
Step 3: Derive the Architectural Plan
From the "Workflow" sections in these Markdown files, the agent constructs a high-level implementation plan. For a file upload feature, this includes configuring Kestrel limits, adding antiforgery policies, creating validation logic, and mapping endpoints. For Web APIs, the plan involves defining sealed-record DTOs, service interfaces, and typed result patterns.
Step 4: Generate Code Aligned with Best Practices
The agent emits C# snippets that follow the exact patterns shown in the skill files. Generated code is inserted into appropriate project locations, typically Program.cs for minimal APIs. The agent uses signatures like TypedResults, IFormFile, and AddOpenApi as specified in the skill definitions, ensuring compatibility with .NET 9+ built-in OpenAPI providers rather than external dependencies like Swashbuckle.
Step 5: Validate Against the Skill Checklist
The agent runs verification against the skill's "Validation" checklist, typically found around line 600 in the dotnet-webapi skill. This programmatic verification ensures that endpoints return correct HTTP status codes, anti-forgery tokens are properly configured (or explicitly disabled for API-only scenarios), and file uploads respect magic-byte validation.
Step 6: Document and Test the Implementation
Following the skill's "Create a .http test file" step, the agent generates .http files with example requests and updates OpenAPI metadata. This closes the loop by providing runnable documentation that matches the implemented architecture.
Code Generation Examples from dotnet-aspnetcore Skills
Minimal API File Upload with Security-First Patterns
The minimal-api-file-upload skill enforces dual size-limit configuration and magic-byte validation to prevent security vulnerabilities. The generated code configures both Kestrel server limits and FormOptions, then validates file content types against actual file headers rather than just the Content-Type header.
var builder = WebApplication.CreateBuilder(args);
// Configure request-size limits (both Kestrel and FormOptions)
builder.WebHost.ConfigureKestrel(o => o.Limits.MaxRequestBodySize = 10 * 1024 * 1024);
builder.Services.Configure<FormOptions>(o => o.MultipartBodyLengthLimit = 10 * 1024 * 1024);
var app = builder.Build();
app.MapPost("/upload", async (IFormFile file) =>
{
// Verify content type against magic bytes
var allowed = new[] { "image/jpeg", "image/png" };
if (!allowed.Contains(file.ContentType, StringComparer.OrdinalIgnoreCase))
return Results.BadRequest("File type not allowed");
await using var stream = file.OpenReadStream();
var header = new byte[8];
await stream.ReadAsync(header);
var isJpeg = header[0] == 0xFF && header[1] == 0xD8 && header[2] == 0xFF;
var isPng = header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47;
var detected = isJpeg ? "image/jpeg" : isPng ? "image/png" : null;
if (detected is null || !string.Equals(file.ContentType, detected, StringComparison.OrdinalIgnoreCase))
return Results.BadRequest("Mismatched content type");
var safeName = $"{Guid.NewGuid()}{(detected == "image/jpeg" ? ".jpg" : ".png")}";
var path = Path.Combine("uploads", safeName);
Directory.CreateDirectory("uploads");
await using var outFile = File.Create(path);
stream.Position = 0;
await stream.CopyToAsync(outFile);
return Results.Ok(new { FileName = safeName, file.Length });
}).DisableAntiforgery(); // API-only endpoint
app.Run();
Key enforcements from the skill include explicit anti-forgery opt-out for API endpoints, safe filename generation using Guid.NewGuid(), and content-type validation against file magic bytes rather than trusting client headers.
Building Typed CRUD Endpoints with Sealed Record DTOs
The dotnet-webapi skill mandates sealed-record DTOs for immutable data contracts and TypedResults for compile-time OpenAPI inference. The agent generates service interfaces with CancellationToken support and maps endpoints using explicit return types.
// DTOs – sealed records with XML comments (auto-included in OpenAPI)
/// <summary>Request payload for creating a product.</summary>
public sealed record CreateProductRequest(string Name, decimal Price, string Category);
/// <summary>Response payload for a product.</summary>
public sealed record ProductResponse(int Id, string Name, decimal Price, string Category, DateTimeOffset CreatedAt);
// Service interface (DI-friendly)
public interface IProductService
{
Task<IReadOnlyList<ProductResponse>> GetAllAsync(CancellationToken ct);
Task<ProductResponse?> GetByIdAsync(int id, CancellationToken ct);
Task<ProductResponse> CreateAsync(CreateProductRequest req, CancellationToken ct);
}
// Minimal-API registration (TypedResults with explicit return type)
app.MapGet("/api/products", async (IProductService svc, CancellationToken ct) =>
TypedResults.Ok(await svc.GetAllAsync(ct)));
app.MapGet("/api/products/{id:int}", async (int id, IProductService svc, CancellationToken ct) =>
await svc.GetByIdAsync(id, ct) is { } p
? TypedResults.Ok(p)
: TypedResults.NotFound());
app.MapPost("/api/products", async (CreateProductRequest req, IProductService svc, CancellationToken ct) =>
{
var created = await svc.CreateAsync(req, ct);
return TypedResults.Created($"/api/products/{created.Id}", created);
});
The skill requires DateTimeOffset for timestamps to ensure timezone-aware data, and the agent configures AddProblemDetails globally for standardized error responses.
Configuring OpenTelemetry for Observability
The configuring-opentelemetry-dotnet skill guides agents to add tracing pipelines using only built-in extensions compatible with the target framework, avoiding version conflicts.
builder.Services.AddOpenTelemetry()
.WithTracing(tracerProvider => tracerProvider
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddJaegerExporter(opts =>
{
opts.AgentHost = builder.Configuration["Jaeger:Host"];
opts.AgentPort = int.Parse(builder.Configuration["Jaeger:Port"]);
}));
var app = builder.Build();
app.UseOpenTelemetryPrometheusScrapingEndpoint(); // expose /metrics
This configuration ensures the agent adds instrumentation without pulling in incompatible third-party packages, maintaining the zero-dependency approach recommended for .NET 9+ projects.
Architectural Benefits of Knowledge-Driven AI Agents
- Consistent API Design – All generated endpoints use sealed-record DTOs,
TypedResults, and proper HTTP status codes (e.g.,201 CreatedwithLocationheaders) as defined indotnet-webapi/SKILL.md. - Security-First Defaults – The
minimal-api-file-uploadskill enforces anti-forgery tokens, request size limits, and content-type validation, while the Web API skill mandatesAddProblemDetailsfor error handling. - OpenTelemetry Ready – Agents automatically configure tracing and exporters using the
configuring-opentelemetry-dotnetskill, ensuring observability without manual instrumentation. - Zero-Dependency Generation – For .NET 9+, the skills specify the built-in
AddOpenApiprovider instead of external libraries like Swashbuckle, preventing package version conflicts. - Test-Driven Workflow – Each skill's validation checklist (located around line 600 in the
dotnet-webapiskill) guides the agent to verify that all endpoints return correct status codes and handle errors appropriately.
Summary
- AI agents use markdown-based skill definitions from
plugins/dotnet-aspnetcore/skills/to reason about ASP.NET Core architecture and generate code. - The workflow involves six steps: problem identification, skill loading, architectural planning, code generation, validation against checklists, and documentation creation.
- Generated code follows specific patterns including sealed-record DTOs,
TypedResults, magic-byte validation for file uploads, and built-in OpenAPI providers. - Security enforcements include anti-forgery configuration, request size limits, and
ProblemDetailserror handling. - The self-contained nature of skill files ensures agents remain up-to-date with latest Microsoft conventions without external heuristics.
Frequently Asked Questions
What is the dotnet-aspnetcore skill plugin?
The dotnet-aspnetcore plugin is a collection of Markdown-based skill definitions located in the dotnet/skills repository under plugins/dotnet-aspnetcore/. Each skill, declared in plugin.json, contains architectural patterns, code snippets, and validation checklists that AI agents use to generate ASP.NET Core code following Microsoft best practices.
How does an AI agent validate generated code against skills?
The agent uses the "Validation" checklist section found in each skill file (approximately line 600 in dotnet-webapi/SKILL.md) to programmatically verify the implementation. This includes checking that endpoints return correct HTTP status codes, file uploads respect size limits configured in ConfigureKestrel and FormOptions, and anti-forgery policies are properly applied or explicitly disabled for API endpoints.
What security patterns are enforced by the minimal-api-file-upload skill?
The skill mandates dual request-size limits via builder.WebHost.ConfigureKestrel and builder.Services.Configure<FormOptions>, magic-byte validation to verify file types against actual headers rather than Content-Type strings, safe filename generation using Guid.NewGuid(), and explicit anti-forgery opt-out via .DisableAntiforgery() for API-only endpoints.
How do skills ensure OpenAPI compatibility without external dependencies?
The dotnet-webapi skill instructs agents to use AddOpenApi() and WithOpenApi() methods built into .NET 9+ instead of third-party packages like Swashbuckle. This zero-dependency approach prevents version conflicts and ensures the generated OpenAPI documentation uses native framework features for schema inference and endpoint metadata.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →