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
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
Program.cs structure
- middleware order and registration
- auth model (Identity, JWT, OAuth, cookies)
- endpoint registrations and routing
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> / IOptionsSnapshot<T> for configuration
- Use
ILogger<T> for structured logging
- Use
IHttpClientFactory for HTTP clients (never new HttpClient())
- Use
IHostedService / BackgroundService for background work
Route specialized work to specific skills:
- UI and components →
blazor
- Real-time →
signalr
- RPC →
grpc
- New HTTP APIs →
minimal-apis (prefer unless controllers needed)
- Controller APIs →
web-api
Validate with build, tests, and targeted endpoint checks.
Current Upstream Notes
- ASP.NET Core
v10.0.11 is a servicing release rather than a new programming model. It updates OpenAPI to 2.7.5, fixes restoration of expired client-persisted Blazor circuit state, and refreshes servicing dependencies. Keep the existing middleware and endpoint architecture, then rerun focused OpenAPI, interactive-rendering, auth, and startup tests.
- The August 2026 Microsoft Learn overview for
aspnetcore-10.0 remains the routing entry point for choosing between Blazor, Minimal APIs, controller APIs, SignalR, and gRPC; the refresh does not justify changing an existing app model by itself.
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 |
new HttpClient() |
Socket exhaustion |
IHttpClientFactory |
Sync-over-async (Task.Result) |
Thread pool starvation |
await properly |
Storing secrets in appsettings.json |
Security risk |
User Secrets, Key Vault |
| Catching all exceptions silently |
Hides bugs |
Use IExceptionHandler |
async void in middleware |
Crashes process |
async Task |
| Missing HTTPS redirect |
Security risk |
UseHttpsRedirection() |
Performance Best Practices
- Use async/await everywhere — avoid sync blocking calls
- Pool DbContext properly — use scoped lifetime
- Enable response compression —
UseResponseCompression()
- Use output caching —
UseOutputCache() for .NET 7+
- Profile with diagnostic tools — Visual Studio Diagnostic Tools, PerfView
- Avoid allocations in hot paths — use
Span<T>, pooling
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
1---2name: aspnet-core3description: Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging, and deployment patterns on current .NET. USE FOR: working on ASP.NET Core apps, services, or middleware; changing auth, routing, configuration, hosting, or deployment behavior; deciding between ASP.NET Core sub-stacks. DO NOT USE FOR: unrelated stacks; generic tasks that do not need this specific guidance. INVOKES: inspect the repository context, edit targeted files, and run relevant build, test, lint, or validation commands when changes are made.4---56# ASP.NET Core78## Trigger On910- working on ASP.NET Core apps, services, or middleware11- changing auth, routing, configuration, hosting, or deployment behavior12- deciding between ASP.NET Core sub-stacks such as Blazor, Minimal APIs, or controller APIs13- debugging request pipeline issues14- modernizing legacy ASP.NET to ASP.NET Core1516## Documentation1718- [ASP.NET Core Overview](https://learn.microsoft.com/en-us/aspnet/core/?view=aspnetcore-10.0)19- [ASP.NET Core Middleware](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-10.0)20- [ASP.NET Core Best Practices](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices?view=aspnetcore-10.0)21- [Configuration in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-10.0)22- [Authentication and Authorization](https://learn.microsoft.com/en-us/aspnet/core/security/?view=aspnetcore-10.0)2324### References2526- [patterns.md](references/patterns.md) - Detailed middleware patterns, security patterns, configuration patterns, DI patterns, error handling patterns, and logging patterns27- [anti-patterns.md](references/anti-patterns.md) - Common ASP.NET Core mistakes including HttpClient misuse, async anti-patterns, configuration errors, DI issues, middleware ordering problems, and security vulnerabilities2829## Workflow30311. **Detect the real hosting shape first:**32 - top-level `Program.cs` structure33 - middleware order and registration34 - auth model (Identity, JWT, OAuth, cookies)35 - endpoint registrations and routing36372. **Follow the correct middleware order:**38 ```39 ExceptionHandler → HttpsRedirection → Static Files → Routing40 → CORS → Authentication → Authorization → Rate Limiting41 → Response Caching → Custom Middleware → Endpoints42 ```43443. **Use built-in patterns correctly:**45 - Prefer `IOptions<T>` / `IOptionsSnapshot<T>` for configuration46 - Use `ILogger<T>` for structured logging47 - Use `IHttpClientFactory` for HTTP clients (never `new HttpClient()`)48 - Use `IHostedService` / `BackgroundService` for background work49504. **Route specialized work to specific skills:**51 - UI and components → `blazor`52 - Real-time → `signalr`53 - RPC → `grpc`54 - New HTTP APIs → `minimal-apis` (prefer unless controllers needed)55 - Controller APIs → `web-api`56575. **Validate with build, tests, and targeted endpoint checks.**5859## Current Upstream Notes6061- ASP.NET Core `v10.0.11` is a servicing release rather than a new programming model. It updates OpenAPI to `2.7.5`, fixes restoration of expired client-persisted Blazor circuit state, and refreshes servicing dependencies. Keep the existing middleware and endpoint architecture, then rerun focused OpenAPI, interactive-rendering, auth, and startup tests.62- The August 2026 Microsoft Learn overview for `aspnetcore-10.0` remains the routing entry point for choosing between Blazor, Minimal APIs, controller APIs, SignalR, and gRPC; the refresh does not justify changing an existing app model by itself.6364## Middleware Patterns6566### Correct Order Matters67```csharp68var app = builder.Build();6970app.UseExceptionHandler("/error"); // 1. Catch all exceptions71app.UseHsts(); // 2. Security headers72app.UseHttpsRedirection(); // 3. HTTPS redirect73app.UseStaticFiles(); // 4. Serve static files74app.UseRouting(); // 5. Route matching75app.UseCors(); // 6. CORS policy76app.UseAuthentication(); // 7. Who are you?77app.UseAuthorization(); // 8. Can you access?78app.UseRateLimiter(); // 9. Rate limiting79app.UseResponseCaching(); // 10. Response cache80app.MapControllers(); // 11. Endpoints81```8283### Custom Middleware Pattern84```csharp85public class RequestTimingMiddleware86{87 private readonly RequestDelegate _next;88 private readonly ILogger<RequestTimingMiddleware> _logger;8990 public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)91 {92 _next = next;93 _logger = logger;94 }9596 public async Task InvokeAsync(HttpContext context)97 {98 var sw = Stopwatch.StartNew();99 await _next(context);100 _logger.LogInformation("Request {Path} completed in {Elapsed}ms",101 context.Request.Path, sw.ElapsedMilliseconds);102 }103}104```105106## Configuration Patterns107108### Strongly-Typed Options109```csharp110// appsettings.json111{112 "EmailSettings": {113 "SmtpServer": "smtp.example.com",114 "Port": 587115 }116}117118// Registration119builder.Services.Configure<EmailSettings>(120 builder.Configuration.GetSection("EmailSettings"));121122// Usage123public class EmailService(IOptions<EmailSettings> options)124{125 private readonly EmailSettings _settings = options.Value;126}127```128129### Environment-Based Configuration130```csharp131builder.Configuration132 .AddJsonFile("appsettings.json", optional: false)133 .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true)134 .AddEnvironmentVariables()135 .AddUserSecrets<Program>(optional: true);136```137138## Security Patterns139140### Authentication Setup141```csharp142builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)143 .AddJwtBearer(options =>144 {145 options.TokenValidationParameters = new TokenValidationParameters146 {147 ValidateIssuer = true,148 ValidateAudience = true,149 ValidateLifetime = true,150 ValidateIssuerSigningKey = true,151 ValidIssuer = builder.Configuration["Jwt:Issuer"],152 ValidAudience = builder.Configuration["Jwt:Audience"],153 IssuerSigningKey = new SymmetricSecurityKey(154 Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))155 };156 });157```158159### Authorization Policies160```csharp161builder.Services.AddAuthorization(options =>162{163 options.AddPolicy("AdminOnly", policy =>164 policy.RequireRole("Admin"));165 options.AddPolicy("MinAge18", policy =>166 policy.RequireClaim("Age", "18", "19", "20")); // simplified167});168```169170## Anti-Patterns to Avoid171172| Anti-Pattern | Why It's Bad | Better Approach |173|--------------|--------------|-----------------|174| `new HttpClient()` | Socket exhaustion | `IHttpClientFactory` |175| Sync-over-async (`Task.Result`) | Thread pool starvation | `await` properly |176| Storing secrets in `appsettings.json` | Security risk | User Secrets, Key Vault |177| Catching all exceptions silently | Hides bugs | Use `IExceptionHandler` |178| `async void` in middleware | Crashes process | `async Task` |179| Missing HTTPS redirect | Security risk | `UseHttpsRedirection()` |180181## Performance Best Practices1821831. **Use async/await everywhere** — avoid sync blocking calls1842. **Pool DbContext properly** — use scoped lifetime1853. **Enable response compression** — `UseResponseCompression()`1864. **Use output caching** — `UseOutputCache()` for .NET 7+1875. **Profile with diagnostic tools** — Visual Studio Diagnostic Tools, PerfView1886. **Avoid allocations in hot paths** — use `Span<T>`, pooling189190## Deliver191192- production-credible ASP.NET Core code and config193- a clear request pipeline and hosting story194- verification that matches the affected endpoints and middleware195- security headers and HTTPS configured correctly196197## Validate198199- middleware order is intentional and documented200- security and configuration changes are explicit201- endpoint behavior is covered by tests or smoke checks202- no blocking calls in async context203- secrets are not committed to source control204- health checks are implemented for production readiness