mir-backend-dotnet-aspnetcorelisted
Install: claude install-skill anantbhandarkar/make-it-right
# /mir-backend-dotnet-aspnetcore · Make It Right (ASP.NET Core)
Bottom tier of the chain: `mir-backend` (generic gates) → `mir-backend-dotnet` (CLR runtime model) → **this** (ASP.NET Core / EF Core / Minimal API library mechanics). Run the gates first; load the .NET runtime tier for async model, DI lifetime theory, and thread-pool concerns; reach for *this* at Gate 5 (design mechanics), Gate 6 (implementation), and Gate 7 review. **Runtime-level concerns (sync-over-async deadlock, ConfigureAwait(false), ValueTask, IDisposable, CancellationToken propagation, captive dependency theory) live in `mir-backend-dotnet` — not here.**
**Stack assumed:** ASP.NET Core 8+ (controllers or Minimal APIs) · EF Core 8 · SQL Server / PostgreSQL · `Microsoft.EntityFrameworkCore.Design` migrations. If the project uses Dapper or a different ORM, note the divergence before applying EF-specific guidance.
## The ASP.NET Core footguns AI walks into most
### 1. DI lifetimes in practice — AddDbContext is Scoped; singletons must not capture it
`AddDbContext<T>()` registers `DbContext` as **Scoped** (one instance per HTTP request). The captive dependency problem (runtime tier) surfaces concretely here:
```csharp
// WRONG — MyWorker is Singleton; captures a Scoped DbContext at construction
services.AddSingleton<MyWorker>();
services.AddDbContext<AppDbContext>();
public class MyWorker(AppDbContext db) { ... } // db lives forever = cross-request bleed
```
```csharp
// RIGHT — use IDbContextFactory