Claude Code .NET C# ASP.NET Core CLAUDE.md Entity Framework Core 2026

Claude Code for .NET and C#: CLAUDE.md Rules for ASP.NET Core, EF Core, and C# 14 (2026)

The Prompt Shelf ·

.NET has quietly become one of the least-covered stacks in the Claude Code CLAUDE.md ecosystem, which is strange given how many enterprise codebases run on it. Most of what exists is either a generic “C# best practices” list lifted from a style guide, or a single .cursorrules file ported over without adjusting for what actually breaks when an agent — not a human — is the one making architectural calls. Neither answers the questions that actually cost review time: minimal APIs or controllers, where DTOs live, which DI lifetime a new service should get, and whether a class should be a record or not.

We read Microsoft’s own .NET 10 and C# 14 documentation, checked the gallery’s existing ASP.NET Core rule data against it, and built a template around the decisions Claude Code gets wrong most often on real .NET codebases — not the ones every “AI coding rules” roundup already lists.

Browse real-world CLAUDE.md and AGENTS.md examples — including an ASP.NET Core + ABP Framework rule set — in our gallery.

Why Generic “C# Best Practices” Rules Don’t Cover .NET

A rules file written for “C#” as a language misses everything that makes a .NET project consistent, because C# the language tolerates almost any architecture equally well. Without .NET-specific rules, Claude Code tends to:

  • Default to controller-based MVC on a project that’s standardized on minimal APIs, or the reverse
  • Register a new service with AddScoped when the rest of the codebase uses AddSingleton for stateless services, or vice versa
  • Write a plain class where the codebase has settled on record types for DTOs and value objects
  • Return domain entities directly from an API endpoint instead of mapping to a response DTO
  • Generate an EF Core migration without checking whether the project uses Migrations folder conventions or a code-first flow that’s supposed to go through a specific dotnet ef invocation
  • Use Console.WriteLine or Debug.WriteLine instead of the project’s actual ILogger<T> injection

None of these fail the build. dotnet build succeeds either way — that’s exactly why they don’t get caught until code review, and why a CLAUDE.md earns its keep more on .NET than on stacks where the compiler is stricter about structure.

C# 14 and .NET 10 Changes Worth Putting in CLAUDE.md

.NET 10 shipped as a 3-year LTS release, and C# 14 added several features that change what “idiomatic” code looks like — which matters because Claude Code’s training data skews toward older C# patterns unless you tell it otherwise:

  • The field keyword — auto-property accessors can now reference a compiler-synthesized backing field directly (set => field = value.Trim();), which replaces a lot of boilerplate manually-backed properties used to need
  • Extension membersextension blocks now support extension properties, static members, and operators, not just methods, which changes how utility code gets organized
  • Implicit span conversions — array-to-Span<T>/ReadOnlySpan<T> conversions no longer need explicit casts, which shows up in method signatures Claude Code writes for anything performance-sensitive
  • User-defined compound assignment operators — custom += on your own types is now possible without falling back to operator +

If your codebase has adopted these, say so explicitly. If it hasn’t yet — plenty of production codebases stay a version or two behind — say that too, because otherwise Claude Code may write C# 14 syntax that doesn’t compile against your <LangVersion> pin.

A CLAUDE.md Template for ASP.NET Core Projects

# CLAUDE.md — .NET Project

## Stack
- .NET {version} ({LTS/STS}), C# {LangVersion}
- API style: {Minimal APIs / Controllers} — do not mix within the same feature area
- Database: {SQL Server / PostgreSQL} via EF Core {version}
- Testing: xUnit + {FluentAssertions/Moq/NSubstitute}

## Architecture Rules
- API endpoints return DTOs (`{Feature}Response`), never EF Core entities directly.
- Business logic lives in application/service classes, not in endpoint handlers or controller actions.
- New services default to `AddScoped` unless they're stateless and thread-safe, in which case `AddSingleton`. Never `AddScoped` inside a background service — it will throw at resolution.
- Use `record` for DTOs and value objects; use `class` for entities tracked by EF Core.
- Validate input with {FluentValidation / DataAnnotations + minimal API filters} — do not validate inline in the handler body.

## Naming Conventions
- DTOs: `{Resource}Request` / `{Resource}Response`.
- Interfaces: `I{Name}`, implementation `{Name}`, e.g. `IInvoiceService` / `InvoiceService`.
- EF Core entities: singular noun matching the domain concept, not the table name.

## Entity Framework Core
- New columns require a migration: `dotnet ef migrations add {Name} --project {ProjectPath}`.
- Never run `dotnet ef database drop` or apply a migration directly against a non-local connection string.
- Check `{Entity}Configuration.cs` (IEntityTypeConfiguration) before assuming a column's constraints — don't infer them from the entity class alone.
- Use `.AsNoTracking()` for read-only queries; omit it only when the entity will be modified and saved in the same scope.

## Testing (xUnit)
- New endpoints require a test covering the happy path and at least one validation/authorization failure.
- Use {WebApplicationFactory / TestServer} for integration tests, not a live database unless explicitly marked `[Trait("Category","Integration")]`.
- Run `dotnet test` before marking any task complete.

## Commands
- Build: `dotnet build`
- Test: `dotnet test`
- Format: `dotnet format`
- Run: `dotnet run --project {ProjectPath}`

Fill in the stack section with what the project actually uses — a CLAUDE.md that claims minimal APIs on a controller-based codebase, or vice versa, causes more churn than having no file at all, because Claude Code will follow the file over the surrounding code when the two disagree.

settings.json: Pre-Approving the dotnet CLI

The default Claude Code permission prompts fire on every dotnet build and dotnet test call unless you pre-approve them, which adds up fast on a .NET project where those two commands run constantly:

{
  "permissions": {
    "allow": [
      "Bash(dotnet build:*)",
      "Bash(dotnet test:*)",
      "Bash(dotnet format:*)",
      "Bash(dotnet restore:*)",
      "Bash(dotnet ef migrations add:*)",
      "Bash(dotnet ef migrations list:*)",
      "Bash(git status)",
      "Bash(git diff:*)"
    ],
    "deny": [
      "Bash(dotnet ef database drop:*)",
      "Bash(dotnet ef database update:* --connection *)"
    ]
  }
}

Pair this with a PostToolUse hook that runs dotnet format automatically after Claude Code edits a .cs file, so formatting drift never reaches a diff:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "if [[ \"$CLAUDE_FILE_PATH\" == *.cs ]]; then dotnet format --include \"$CLAUDE_FILE_PATH\"; fi"
          }
        ]
      }
    ]
  }
}

The deny list matters more here than on most stacks: dotnet ef database drop and an unscoped database update are genuinely destructive against a real connection string, and unlike a file edit, there’s no undo.

AGENTS.md for Multi-Project Solutions

A typical .NET solution isn’t one project — it’s an API, a class library for domain logic, an EF Core data layer, and a test project, each with its own conventions. Scoping instructions by directory keeps Claude Code from bleeding API-layer patterns into the domain layer:

# AGENTS.md

## Global Rules
- Follow all rules in CLAUDE.md.
- Run `dotnet build` and `dotnet test` before marking any task complete.
- Never edit `appsettings.Production.json`; use `appsettings.Development.json` locally.

## /src/Api/
Agent scope: HTTP layer (minimal API endpoints or controllers).
- Endpoints map to DTOs via a mapping method or Mapperly — never return an EF Core entity from an endpoint.
- Authorization goes through `[Authorize]` policies defined in `Program.cs`, not ad hoc claims checks inside a handler.

## /src/Domain/
Agent scope: Business logic, entities, domain services.
- This project has no reference to `Microsoft.AspNetCore.*` or `Microsoft.EntityFrameworkCore` — if a change would require one, it belongs in a different layer.
- Domain entities enforce their own invariants in constructors/methods, not in the API layer.

## /src/Infrastructure/
Agent scope: EF Core `DbContext`, repository implementations, external service clients.
- All entity configuration goes in `IEntityTypeConfiguration<T>` classes, not `OnModelCreating` fluent chains in `DbContext`.
- New external service clients register via `IHttpClientFactory` (`AddHttpClient<T>`), not a manually constructed `HttpClient`.

This matters more on .NET than on single-project stacks specifically because the Domain project having zero framework references is often an intentional architectural constraint (Clean Architecture, Onion Architecture) — and it’s exactly the kind of rule an agent has no way to infer just by reading the code, since nothing stops you from adding an EF Core reference to a domain project except discipline.

Minimal API + EF Core vs. Clean Architecture with ABP

Not every .NET project should follow the same shape, and the CLAUDE.md above assumes a fairly conventional layered API. For comparison, here’s a rule set from our gallery built for ABP Framework — a much more prescriptive DDD/Clean Architecture stack on top of ASP.NET Core and EF Core:

Minimal API + EF Core (this guide)ASP.NET Core + ABP Framework
LayeringConvention, enforced by team disciplineEnforced by ABP’s module system and project templates
DI lifetimesManual AddScoped/AddSingleton callsConvention-based via ABP’s dependency injection conventions
CRUD boilerplateHand-written or Mapperly-generatedAuto-generated application services via CrudAppService
Best fitSmall-to-mid APIs, teams that want minimal framework overheadLarger enterprise apps that want DDD structure enforced out of the box

If a project already uses ABP, its generated CLAUDE.md/rules should reflect ABP’s own conventions (IApplicationService, CrudAppService<T>, module-based DI registration) rather than the manual template above — mixing the two produces code that fights the framework.

Common Mistakes to Watch For

Mixing minimal APIs and controllers in the same feature. Both are valid, but a project that’s standardized on one and gets a controller added for “just this one endpoint” now has two routing conventions to maintain. Say which one the project uses.

AddScoped inside a background service. IHostedService and BackgroundService implementations run outside the request scope, so injecting a scoped service directly throws at runtime. The fix — creating a scope manually via IServiceScopeFactory — is easy to forget without an explicit rule.

Returning EF Core entities from API endpoints. It works until a navigation property triggers lazy-loading during JSON serialization, or the entity’s shape leaks a column that was never meant to be public. Mapping to a DTO isn’t optional ceremony here.

Assuming migration files reflect current schema. On a project with squashed or manually edited migrations, the migration history doesn’t match the live database. Check the entity configuration classes, or better, the actual database schema, before writing code that depends on column constraints.

Skipping .AsNoTracking() on read-only queries. Left unguided, Claude Code writes tracked queries by default, which is fine for a single request but adds real overhead on list/report endpoints that never modify the data they read.


.NET’s flexibility is the whole reason a CLAUDE.md pays off here — the language and framework won’t stop an agent from picking a valid-but-inconsistent pattern, so the file has to. Fill in the stack section honestly, pick minimal APIs or controllers and say so, and the rest of the template above covers the DI, EF Core, and testing conventions that cause the most review churn on real .NET codebases.

Browse more real .NET, C#, and framework-specific CLAUDE.md/AGENTS.md examples in our gallery.


FAQ

Does Claude Code work well with .NET and C#? Yes — Claude Code handles C# and the .NET CLI (dotnet build, dotnet test, dotnet ef) without any special setup. The gap isn’t capability, it’s that .NET’s architectural flexibility (minimal APIs vs. controllers, DI lifetimes, layering) needs to be pinned down in CLAUDE.md, since the compiler won’t enforce project-specific conventions on its own.

Should CLAUDE.md specify minimal APIs or controllers? Yes, explicitly. Both are fully supported in ASP.NET Core, and Claude Code will default to whichever pattern is more common in its training data unless the project states which one it actually uses — mixing both in the same feature area is one of the more common inconsistencies on unguided .NET projects.

How do I stop Claude Code from using outdated C# syntax? State the project’s actual <LangVersion> and target framework in the CLAUDE.md stack section. C# 14 features like the field keyword and extension properties are only valid on .NET 10 / C# 14 projects — without that context, Claude Code may either miss newer idioms or write syntax that doesn’t compile against an older LangVersion pin.

What’s the difference between the manual template and ABP Framework’s conventions? The manual template in this guide assumes a conventional, hand-structured ASP.NET Core + EF Core project where layering is enforced by team discipline. ABP Framework enforces DDD/Clean Architecture through its module system and code generation (CrudAppService, convention-based DI), so a project using ABP should base its CLAUDE.md on ABP’s own conventions instead.

Why does the deny list block dotnet ef database drop? Because it’s irreversible against a real connection string and Claude Code has no way to distinguish a local development database from a shared one just by looking at the command. Explicitly denying destructive dotnet ef database commands in settings.json forces a human to run them manually.

Related Articles

Explore the collection

Browse all AI coding rules — CLAUDE.md, .cursorrules, AGENTS.md, and more.

Browse Rules