Complete AI prompt library for .NET developers. Covers Minimal APIs and Controllers, Entity Framework Core, JWT authentication with ASP.NET Identity, MediatR CQRS pattern, xUnit testing, Azure deployment, and performance with output caching.
ASP.NET Core in 2026: Microsoft's High-Performance Web Framework
.NET 9 with ASP.NET Core delivers some of the highest throughput numbers in the web framework benchmarks. C# 13, Primary Constructors, Minimal APIs, and Native AOT compilation make it a compelling choice for high-performance microservices. The key to productive AI prompting for .NET is specifying the modern patterns — Minimal APIs, MediatR CQRS, Result pattern, and EF Core 9 — rather than the MVC + DataAnnotations approach from .NET Framework era.
AI + .NET 9: The Legacy Pattern Trap
.NET has reinvented itself more radically than any other enterprise framework over the last decade. The practical consequence for AI: .NET Framework and early .NET Core patterns dominate training data because they existed for 15+ years before modern .NET arrived. Ask a model for a new endpoint without specifying the target version and you'll get MVC controllers with DataAnnotations, synchronous EF Core calls inside async methods, and Task.Result blocks that are deadlocks waiting to happen. The code compiles, passes casual review, and breaks under load.
Two instructions that prevent the most common .NET regressions: (1) "Use .NET 9 Minimal APIs (not MVC controllers), FluentValidation (not DataAnnotations), and the Result pattern for error handling — no exceptions for control flow." (2) "Strict async hygiene: no Task.Result, no .GetAwaiter().GetResult(), no async void except event handlers." Claude catches async hygiene violations most reliably. For EF Core specifically, always add: "Use AsNoTracking() on all read queries and Include() / ThenInclude() for all relationships — no lazy loading."
For the cross-framework model comparison covering .NET alongside Flutter, see the Cross-Platform & Enterprise AI Prompts guide.
1. Minimal API with CQRS via MediatR
You are a senior .NET 9 architect using C# 13.
Build a complete Task API using ASP.NET Core Minimal APIs with MediatR CQRS pattern:
Endpoint registration (TaskEndpoints.cs — extension method on WebApplication):
- GET /api/v1/tasks — GetTasksQuery
- GET /api/v1/tasks/{id:guid} — GetTaskByIdQuery
- POST /api/v1/tasks — CreateTaskCommand
- PUT /api/v1/tasks/{id:guid} — UpdateTaskCommand
- DELETE /api/v1/tasks/{id:guid} — DeleteTaskCommand
Each endpoint:
- [Authorize] attribute or RequireAuthorization() with policy name
- Extract organizationId from JWT claims (ClaimsPrincipal extension method)
- Send to IMediator.Send()
- Return TypedResults (Results<Ok<TaskDto>, NotFound, ForbidHttpResult, ValidationProblem>)
Commands/Queries (records):
- GetTasksQuery(Guid OrganizationId, TaskStatus? Status, int Page, int PageSize) : IRequest<PagedResult<TaskDto>>
- CreateTaskCommand(string Title, string? Description, DateOnly? DueDate, Guid ProjectId, Guid OrganizationId) : IRequest<Result<TaskDto>>
Result pattern: Result<T> with IsSuccess, Value, Error (no exceptions for expected failures).
Output: endpoint registration, commands/queries as records, handlers, and Program.cs registration.
2. Entity Framework Core 9 Configuration
You are an EF Core 9 expert.
Design EF Core 9 entity configurations for a multi-tenant task management system:
Entities (C# 13 primary constructors):
- Organization, User, Project, Task, Comment, AuditLog
IEntityTypeConfiguration<Task> (TaskConfiguration : IEntityTypeConfiguration<Task>):
- Table name, schema: tasks schema
- Primary key: Guid (NewId() from UlidId or sequential GUID for index friendliness)
- Soft delete: IsDeleted (bool) + DeletedAt (DateTime?) with global query filter
- Tenant filter: global query filter for OrganizationId == currentTenantId (injected via ITenantContext)
- Indexes: composite [OrganizationId, Status, DueDate], [OrganizationId, AssignedToId]
- Value conversions: TaskStatus enum → string (not int for readability in DB)
- Owned entity: Task.Address as owned type (no separate table)
- Concurrency: RowVersion byte[] property for optimistic concurrency
Bulk operations (EF Core 7+):
- ExecuteUpdateAsync for bulk status changes (no entity loading)
- ExecuteDeleteAsync for hard delete admin operations
Repository:
- ITaskRepository with async methods, CancellationToken on all
- Specification pattern: ISpecification<T> for reusable query building
Output: entity configurations, DbContext with all entity registrations, repository interface + EF implementation.
3. JWT Authentication with ASP.NET Identity
You are a .NET security engineer.
Implement JWT authentication for ASP.NET Core 9 with ASP.NET Identity:
Identity configuration:
- ApplicationUser extends IdentityUser with: OrganizationId (Guid), Role (enum), CreatedAt, LastLoginAt
- IdentityOptions: strong password policy, lockout after 5 failures for 15 minutes, require confirmed email
JWT setup (Program.cs):
- AddAuthentication().AddJwtBearer() with RSA256 (load public key from env for validation)
- Token issuer: separate TokenService
- Validate: issuer, audience, lifetime, signing key
TokenService:
- GenerateAccessToken(ApplicationUser user): RS256, 15-minute lifetime, claims: sub, email, organizationId, role, jti
- GenerateRefreshToken(): opaque 32-byte random, stored in RefreshTokens table with userId, expiresAt, isRevoked
- RevokeRefreshToken(token): mark as revoked, optional: revoke entire family on reuse detection
- RefreshAccessToken(refreshToken): validate table entry → generate new access token + rotate refresh token
Auth endpoints (/api/auth):
- POST /login: Identity SignInManager, return token pair
- POST /refresh: validate refresh token table
- POST /logout: revoke refresh token
- POST /register: create user, send confirmation email via IEmailSender
Output: TokenService, AuthController (or Minimal API), Identity configuration in Program.cs.
4. MediatR Pipeline Behaviors
You are a MediatR expert for .NET applications.
Build a production MediatR pipeline with behaviors (in execution order):
1. LoggingBehavior<TRequest, TResponse>:
- Log: request type, request payload (sanitize sensitive fields), duration, user ID from ICurrentUser
- Structured logging with Serilog: include correlationId, userId, organizationId as enrichers
- Warn if handler takes longer than 500ms
2. ValidationBehavior<TRequest, TResponse>:
- Run all IValidator<TRequest> registered via FluentValidation
- On failure: return Result.Failure with ValidationError list (not throw exception)
- Only run for commands (implement ICommand marker interface check)
3. AuthorizationBehavior<TRequest, TResponse>:
- Check IAuthorizeRequest on command/query
- Call IAuthorizationService with the required policy name
- Return Result.Failure(Error.Forbidden) if denied
4. TransactionBehavior<TRequest, TResponse>:
- Wrap commands (ICommand) in EF Core DbContext.BeginTransactionAsync
- Commit on success, rollback on exception
- Do NOT apply to queries
5. CachingBehavior<TRequest, TResponse>:
- For queries implementing ICacheable (with CacheKey and CacheDuration properties)
- Read from IDistributedCache, deserialize, return early if hit
- On miss: execute handler, write to cache
Output: all 5 behavior classes, ICurrentUser interface + HttpContext implementation, FluentValidation registration in Program.cs.
5. xUnit Integration Tests with WebApplicationFactory
You are a .NET testing expert.
Write integration tests for the Task API using xUnit and WebApplicationFactory:
Test infrastructure:
- CustomWebApplicationFactory<Program>: replace real DB with Testcontainers PostgreSQL, override JWT validation to accept test tokens
- DatabaseFixture: IAsyncLifetime — create schema on InitializeAsync, truncate tables between tests
- TestJwtTokenFactory: generate signed JWT with any claims for test users
- ApiClient: HttpClient wrapper with typed methods (GetTaskAsync, CreateTaskAsync, etc.)
Test cases (Fact and Theory):
[Fact] CreateTask_WithValidData_Returns201AndCreatedTask
[Fact] CreateTask_AsMemberOfDifferentOrg_Returns403
[Theory, InlineData("", "Title required"), InlineData("ab", "Min 3 chars")]
CreateTask_WithInvalidTitle_Returns400WithFieldError(string title, string expectedMessage)
[Fact] GetTasks_ReturnsOnlyCurrentOrgTasks_TenantIsolation
[Fact] UpdateTask_WithStaleVersion_Returns409Conflict
[Fact] DeleteTask_SoftDeletes_NotReturnedInSubsequentGet
Assertions:
- HTTP status code (FluentAssertions: response.Should().HaveStatusCode(201))
- Response body JSON (deserialize to DTO, assert fields)
- Database state (inject IDbContextFactory, query DB directly to assert persistence)
Output: WebApplicationFactory, DatabaseFixture, test token factory, and all test cases.
7. SignalR Real-Time with .NET 9
You are a senior .NET 9 real-time systems engineer.
Add SignalR to an ASP.NET Core 9 Minimal API application for live collaboration features:
Hub: TaskHub : Hub
- OnConnectedAsync: join group for user's tenantId, send pending notifications count
- OnDisconnectedAsync: log disconnect, remove from group
- Methods:
- UpdateTask(string taskId, TaskUpdateDto update): validate user permission, broadcast to tenant group, persist change
- JoinTaskRoom(string taskId): add to task-specific group for field-level updates
- TypingIndicator(string taskId, bool isTyping): broadcast to others in task room (not back to sender)
- SendMessage(string taskId, string content): add to real-time comment stream
Authentication: JWT bearer token via query string (?access_token=) — SignalR specific setup in Program.cs
Scale-out: Azure SignalR Service or Redis backplane for multiple instances
Client TypeScript: generated via @microsoft/signalr, typed method calls using HubConnection
Output: TaskHub class, Program.cs SignalR registration with Redis backplane, JWT config for SignalR, and TypeScript client hook useTaskHub(taskId).
8. Background Services with .NET Hosted Services
You are a .NET 9 backend engineer.
Implement background processing using IHostedService and BackgroundService in ASP.NET Core 9:
Services to implement:
1. SubscriptionExpiryWorker (BackgroundService): runs every hour, finds organizations with subscriptions expiring in next 24h, queues renewal reminder emails via IEmailQueue, idempotent (cache processed IDs in Redis for 26h)
2. MetricsAggregator (BackgroundService): runs every 5 minutes, computes org-level stats (active users, task completion rate), writes to PostgreSQL summary table with UPSERT
3. FileCleanupService (IHostedService): on startup, delete S3 objects with status=orphaned older than 7 days (created without DB record)
Common requirements:
- CancellationToken: respect stoppingToken — check IsCancellationRequested in loops, pass to async DB calls
- Structured logging: ILogger<T> with scope including service name and run ID
- Error isolation: catch exceptions per iteration, log and continue — one bad record should not stop the worker
- Graceful shutdown: override StopAsync, drain current work within 30s
- Health checks: custom IHealthCheck for each worker showing last run time and status
Output: all three service classes, Program.cs registration, and the health check implementations.
End-to-End Workflow: Minimal API Feature with CQRS
Shipping a new feature following the MediatR CQRS pattern in .NET 9:
- Domain (Prompt 2 variant): "Create a Comment EF Core 9 entity for a task management app: Id (Guid, generated), TaskId (Guid FK), AuthorId (Guid FK), Content (string max 5000), IsEdited (bool), EditedAt (DateTime?), CreatedAt. Configure with Fluent API: HasIndex([TaskId, CreatedAt]), HasQueryFilter for soft-delete."
- Command/Query: "Create a CreateCommentCommand (record): TaskId, AuthorId, Content. CreateCommentHandler implements IRequestHandler<CreateCommentCommand, Result<CommentDto>>. Validate with FluentValidation (content not empty, max 5000 chars, taskId exists in DB). Use Result pattern — no exceptions for validation."
- Minimal API endpoint (Prompt 1 variant): "Map POST /tasks/{taskId}/comments Minimal API endpoint. Extract AuthorId from ClaimsPrincipal. Send CreateCommentCommand via IMediator. Map Result to 201/400/403/404 IResult responses using TypedResults."
- Tests (Prompt 5 variant): "Write xUnit integration tests using WebApplicationFactory for POST /tasks/{taskId}/comments. Use Testcontainers for PostgreSQL. Test 201 success, 400 content validation, 403 cross-tenant, 404 task not found."
Where AI Goes Wrong in .NET
- Sync-over-async patterns. AI generates
Task.Result,.GetAwaiter().GetResult(), andasync voidin ASP.NET Core contexts. These cause deadlocks under load. Specify "no sync-over-async, no async void except for event handlers" explicitly. - .NET 5/6 patterns in .NET 9 projects. AI still generates
Startup.cswith separate ConfigureServices/Configure methods, and the old WebHost builder. .NET 9 uses the minimal hosting model with Program.cs and WebApplication.CreateBuilder. Specify ".NET 9 minimal hosting model." - DataAnnotations instead of FluentValidation. DataAnnotations work but don't support complex validation logic, don't compose well, and mix concerns. FluentValidation as a MediatR pipeline behavior is the correct pattern. Always specify "FluentValidation, not DataAnnotations."
- Entity Framework: tracking queries where AsNoTracking is needed. AI generates queries without AsNoTracking() for read-only operations. Every query that doesn't need to update the result should use AsNoTracking() — otherwise EF Core caches entity state and consumes memory unnecessarily.
- Missing CancellationToken propagation. AI-generated async methods often don't accept or propagate CancellationToken. Without it, a client disconnect doesn't stop long-running DB queries. Add CancellationToken to every async method signature and pass it through.
6. Good vs Bad .NET Prompts
| Task | ❌ Bad Prompt | ✅ Good Prompt |
|---|---|---|
| API design | "Build a REST API in C#" | "Build ASP.NET Core 9 Minimal API for Task resource: MediatR commands/queries as C# 13 records, TypedResults return types, RequireAuthorization() per endpoint, extract OrganizationId from JWT claims, return ValidationProblem on FluentValidation failure. Result pattern for error handling." |
| EF Core | "Query tasks from database" | "Write EF Core 9 query for tasks: AsNoTracking() for read, Include(t => t.Assignee) + Include(t => t.Project), global query filter for soft delete + tenant isolation, ExecuteUpdateAsync for bulk status change. Add composite index [OrganizationId, Status, DueDate] in IEntityTypeConfiguration." |
| Testing | "Write unit tests for my API" | "Write xUnit integration tests with WebApplicationFactory: Testcontainers PostgreSQL, override JWT for test tokens, FluentAssertions, test tenant isolation (403 cross-org), test optimistic concurrency (409 on stale RowVersion), assert DB state via IDbContextFactory." |
Before You Prompt: .NET & C# Context Setup
.NET 9 and C# 13 introduce patterns that AI models trained on .NET 5/6 code don't know: Primary Constructors, Minimal APIs, IExceptionHandler, and the updated EF Core 9 API surface. This block keeps AI on the modern path and prevents the two most common antipatterns (DataAnnotations and IRepository wrappers):
Context for all .NET prompts in this session:
- Platform: .NET 9, C# 13
- API style: Minimal APIs in endpoint classes (NOT MVC Controllers unless I specify)
- Architecture: CQRS with MediatR 12 — Commands and Queries as C# records
- Validation: FluentValidation 12 as a MediatR pipeline behavior (NOT DataAnnotations)
DataAnnotations are for display metadata only — never for domain validation
- Database: Entity Framework Core 9 + Npgsql (PostgreSQL)
Use AsNoTracking() on all read-only queries
- Nullable: #nullable enable in all files
- Testing: xUnit + WebApplicationFactory + Testcontainers.PostgreSql
NEVER EF Core InMemory provider — it doesn't enforce relational constraints
Never generate:
- IRepository<T> wrapping EF Core (EF Core IS the repository — double abstraction hurts)
- DataAnnotations on domain models ([Required], [MaxLength] etc.)
- .NET Framework APIs (System.Web, HttpWebRequest — use HttpClient + IHttpClientFactory)
The IRepository ban is counterintuitive but important. Wrapping EF Core in a generic repository loses EF Core's most powerful features: IQueryable composition, change tracking, and explicit transaction control. It also makes unit testing harder, not easier — you mock the repository but lose EF Core's behavior. Test the real database with Testcontainers instead.
3 Common Mistakes When Prompting AI for .NET
Mistake 1: DataAnnotations for domain validation
Asking for "a User model with validation" produces a class covered in [Required], [MaxLength(255)], [EmailAddress] attributes. These annotations work in MVC model binding but can't be reused outside controllers, can't express cross-field rules, and leak presentation concerns into the domain model. Specify: "FluentValidation 12 with a UserValidator : AbstractValidator<User> class — no DataAnnotations on domain models." The validator is testable in isolation and can be injected as a MediatR pipeline behavior.
Mistake 2: IRepository<T> wrapping EF Core's DbContext
AI generates generic repository interfaces (IRepository<TEntity> with GetById, GetAll, Add, Update, Delete) as a "best practice." This pattern made sense with raw ADO.NET. With EF Core, it hides IQueryable (no filtering without loading all records), loses change tracking (explicit SaveChanges calls break), and makes the codebase harder to read. Specify: "inject DbContext directly in handlers — no IRepository wrapper. Use AsNoTracking() for read-only queries." This is a validated recommendation from the EF Core team.
Mistake 3: EF Core InMemory provider for integration tests
EF Core's InMemory provider doesn't enforce foreign keys, unique constraints, or database triggers. It runs migrations silently without applying them. Tests that pass against InMemory regularly fail against real PostgreSQL because the SQL dialect, constraint enforcement, and transaction isolation are completely different. Specify: "use Testcontainers with a real PostgreSQL 16 container for all integration tests." The startup overhead is ~3–5 seconds per test run — a price worth paying for tests that actually reflect production behavior.
Further Reading
Resources for AI-assisted .NET and C# development:
- How engineering teams use AI to accelerate .NET development — AI strategies for C# teams: Minimal API design, MediatR architecture, and EF Core optimization
- How to write the perfect AI prompt — the principles that make every .NET prompt in this guide produce clean, reviewable output
- AI Coding Prompt Library — 50+ copy-ready prompts for ASP.NET Core, EF Core, MediatR, xUnit, and C# architecture
Generate a custom .NET prompt → Try PromptPrepare free
Help & Answers
Frequently Asked Questions
Found this helpful?
Save it to your library or share with your team.
Keep Reading