Dotnet-skills dotnet-aspnet-core
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET.
install
source · Clone the upstream repo
git clone https://github.com/managedcode/dotnet-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/managedcode/dotnet-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/catalog/Frameworks/ASP.NET-Core/skills/dotnet-aspnet-core" ~/.claude/skills/managedcode-dotnet-skills-dotnet-aspnet-core && rm -rf "$T"
manifest:
catalog/Frameworks/ASP.NET-Core/skills/dotnet-aspnet-core/SKILL.mdsource content
ASP.NET Core
Trigger On
- working on ASP.NET Core apps, services, or middleware
- changing auth, routing, configuration, hosting, or deployment behavior
- deciding between ASP.NET Core sub-stacks such as Blazor, Minimal APIs, or controller APIs
- debugging request pipeline issues
- modernizing legacy ASP.NET to ASP.NET Core
Documentation
- ASP.NET Core Overview
- ASP.NET Core Middleware
- ASP.NET Core Best Practices
- Configuration in ASP.NET Core
- Authentication and Authorization
References
- patterns.md - Detailed middleware patterns, security patterns, configuration patterns, DI patterns, error handling patterns, and logging patterns
- anti-patterns.md - Common ASP.NET Core mistakes including HttpClient misuse, async anti-patterns, configuration errors, DI issues, middleware ordering problems, and security vulnerabilities
Workflow
-
Detect the real hosting shape first:
- top-level
structureProgram.cs - middleware order and registration
- auth model (Identity, JWT, OAuth, cookies)
- endpoint registrations and routing
- top-level
-
Follow the correct middleware order:
ExceptionHandler → HttpsRedirection → Static Files → Routing → CORS → Authentication → Authorization → Rate Limiting → Response Caching → Custom Middleware → Endpoints -
Use built-in patterns correctly:
- Prefer
/IOptions<T>
for configurationIOptionsSnapshot<T> - Use
for structured loggingILogger<T> - Use
for HTTP clients (neverIHttpClientFactory
)new HttpClient() - Use
/IHostedService
for background workBackgroundService
- Prefer
-
Route specialized work to specific skills:
- UI and components →
dotnet-blazor - Real-time →
dotnet-signalr - RPC →
dotnet-grpc - New HTTP APIs →
(prefer unless controllers needed)dotnet-minimal-apis - Controller APIs →
dotnet-web-api
- UI and components →
-
Validate with build, tests, and targeted endpoint checks.
Middleware Patterns
Correct Order Matters
var app = builder.Build(); app.UseExceptionHandler("/error"); // 1. Catch all exceptions app.UseHsts(); // 2. Security headers app.UseHttpsRedirection(); // 3. HTTPS redirect app.UseStaticFiles(); // 4. Serve static files app.UseRouting(); // 5. Route matching app.UseCors(); // 6. CORS policy app.UseAuthentication(); // 7. Who are you? app.UseAuthorization(); // 8. Can you access? app.UseRateLimiter(); // 9. Rate limiting app.UseResponseCaching(); // 10. Response cache app.MapControllers(); // 11. Endpoints
Custom Middleware Pattern
public class RequestTimingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<RequestTimingMiddleware> _logger; public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { var sw = Stopwatch.StartNew(); await _next(context); _logger.LogInformation("Request {Path} completed in {Elapsed}ms", context.Request.Path, sw.ElapsedMilliseconds); } }
Configuration Patterns
Strongly-Typed Options
// appsettings.json { "EmailSettings": { "SmtpServer": "smtp.example.com", "Port": 587 } } // Registration builder.Services.Configure<EmailSettings>( builder.Configuration.GetSection("EmailSettings")); // Usage public class EmailService(IOptions<EmailSettings> options) { private readonly EmailSettings _settings = options.Value; }
Environment-Based Configuration
builder.Configuration .AddJsonFile("appsettings.json", optional: false) .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true) .AddEnvironmentVariables() .AddUserSecrets<Program>(optional: true);
Security Patterns
Authentication Setup
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)) }; });
Authorization Policies
builder.Services.AddAuthorization(options => { options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin")); options.AddPolicy("MinAge18", policy => policy.RequireClaim("Age", "18", "19", "20")); // simplified });
Anti-Patterns to Avoid
| Anti-Pattern | Why It's Bad | Better Approach |
|---|---|---|
| Socket exhaustion | |
Sync-over-async () | Thread pool starvation | properly |
Storing secrets in | Security risk | User Secrets, Key Vault |
| Catching all exceptions silently | Hides bugs | Use |
in middleware | Crashes process | |
| Missing HTTPS redirect | Security risk | |
Performance Best Practices
- Use async/await everywhere — avoid sync blocking calls
- Pool DbContext properly — use scoped lifetime
- Enable response compression —
UseResponseCompression() - Use output caching —
for .NET 7+UseOutputCache() - Profile with diagnostic tools — Visual Studio Diagnostic Tools, PerfView
- Avoid allocations in hot paths — use
, poolingSpan<T>
Deliver
- production-credible ASP.NET Core code and config
- a clear request pipeline and hosting story
- verification that matches the affected endpoints and middleware
- security headers and HTTPS configured correctly
Validate
- middleware order is intentional and documented
- security and configuration changes are explicit
- endpoint behavior is covered by tests or smoke checks
- no blocking calls in async context
- secrets are not committed to source control
- health checks are implemented for production readiness