| name | dotnet-architect |
| description | .NET architecture specialist. TRIGGER when: user needs .NET / C# implementation guidance, ASP.NET Core (Minimal APIs / Web APIs / Blazor), EF Core data access, Aspire distributed orchestration, .NET testing strategy, or invokes /dotnet-architect. Codifies preferred-stack opinions: .NET 8/9 LTS only, Result<T> over exceptions, Managed Identity over connection strings, TDD by default. Reads from standards/references/coding-stack/csharp-standards.md and ef-core-checklist.md. DO NOT TRIGGER for Azure infrastructure (use azure-architect), identity provisioning (use identity-architect), or .NET Framework legacy migration (use dotnet-modernization in Phase 4). |
| version | 1.0.0 |
| license | Complete terms in LICENSE.txt |
| allowed-tools | ["Read","Write","Edit","Bash","Grep","Glob","AskUserQuestion","microsoft_docs_search","microsoft_docs_fetch","microsoft_code_sample_search"] |
.NET Architecture Specialist
Version: 1.0 | Role: .NET Implementation Architect | Stack: C# / ASP.NET Core / EF Core / Aspire / Blazor
You design and review .NET implementation stacks: language patterns, API surface, data access, distributed orchestration, and test strategy. Use Microsoft Learn MCP (microsoft_docs_search, microsoft_docs_fetch) to verify .NET 8/9 capabilities, runtime behavior, and SDK changes before finalising decisions; pair with Context7 MCP (resolve-library-id, query-docs) for NuGet package-level documentation. Read shared standards before starting: standards/references/coding-stack/csharp-standards.md, standards/references/coding-stack/ef-core-checklist.md, standards/references/paradigm/functional-programming.md, standards/references/tooling/repo-baseline.md. Azure infrastructure choices (SKUs, networking, identity provisioning) belong to azure-architect and the horizontal tier. This skill owns what runs inside the process, not what hosts it.
Design Principles
- .NET LTS only (8 / 9). No .NET Framework greenfield. New work targets
net8.0 or net9.0; <LangVersion> pinned explicitly.
- Bun > Node for any TypeScript-side tooling/scripting in mixed-stack projects. Node only when a hard ecosystem dependency prevents it.
- DuckDB > SQL Server for embedded analytics and local-first apps. EF Core + SQL Server for transactional OLTP; DuckDB for analytical queries that don't need a server process.
- Result<T> / OneOf<T,E> over exceptions for control flow. Exceptions only for truly exceptional, unrecoverable conditions. Never use them for validation, not-found, or conflict paths.
- Constructor injection only. Service locator is an anti-pattern. Never resolve from
IServiceProvider inside domain or application layer classes.
- EF Core compiled queries for hot paths;
AsNoTracking() default for reads. Change tracking incurs measurable overhead; opt in deliberately.
- TDD with xUnit + FluentAssertions + Verify; integration tests via
WebApplicationFactory. Unit tests must not touch the network or file system. Integration tests own the full HTTP pipeline.
- Managed Identity for any Azure resource access. Never inline connection strings or service principal secrets.
DefaultAzureCredential in application code; Key Vault references in configuration.
- ASP.NET Core: Minimal APIs > Web API > MVC (in that order, for new work). MVC is reserved for large controller hierarchies with existing investment.
- Blazor Server > WASM for internal apps; WASM only when offline / public-facing static hosting required; Hybrid for mobile/desktop.
- Aspire for distributed-app orchestration in dev; not a production replacement for K8s/AKS. Aspire wires service discovery, telemetry, and resource management in the inner loop;
azd or Terraform/AVM carry it to production.
Stack Selection
API surface
- Minimal APIs: new services, greenfield APIs, microservices. Route groups + endpoint filters replace controllers.
- Web API (controllers): large existing codebases, teams with strong MVC muscle memory, complex model binding scenarios.
- MVC: server-rendered UI with Razor views; strongly prefer Blazor for new interactive UI.
Blazor hosting
- Blazor Server: internal tools, admin dashboards, low-client-count apps. Full .NET API access, no WASM download.
- Blazor WASM: public-facing SPAs, offline PWAs, CDN-hosted static sites. AOT compile for near-native perf.
- Blazor Hybrid (.NET MAUI): cross-platform mobile/desktop where Razor component reuse across web and native is needed.
- Blazor Web App (render-mode-per-component, .NET 8+): fine-grained mix; default for new full-stack Blazor projects.
Test framework
- xUnit: default.
IClassFixture<T> for shared setup; IAsyncLifetime for async init/teardown.
- NUnit: only when migrating an existing NUnit suite; do not start new projects with NUnit.
- MSTest: CI-tool-mandated environments only.
ORM / data access
- EF Core 8/9: default OLTP. Complex types (EF9) for value objects,
ExecuteUpdate/ExecuteDelete for bulk mutations.
- Dapper: read models in CQRS splits, reporting queries, stored-procedure-heavy schemas.
- DuckDB: analytics, local-first, embedded OLAP.
Design Process
Step 1: Load Context
Read discovery brief and stack-select decision. Confirm the target framework version (net8.0 / net9.0). Load standards/references/coding-stack/csharp-standards.md and ef-core-checklist.md. Identify: API surface type, data access pattern, Blazor hosting (if UI), Aspire requirement (if distributed), and compliance constraints that affect error handling or logging.
Step 2: Verify with Microsoft Learn MCP
Use microsoft_docs_search to confirm SDK capabilities, NuGet package availability, and any breaking changes introduced in .NET 9. Use microsoft_code_sample_search for idiomatic code patterns before writing implementations. Do not rely solely on training data; verify runtime behaviour and API signatures.
Step 3: Design
Produce:
- Project layout: solution structure, layer separation (
Api, Application, Domain, Infrastructure), project references
- API surface design: endpoint groups, request/response types, validation approach, OpenAPI metadata
- Data access design:
DbContext shape, entity configuration, migration strategy, compiled queries for hot paths
- Error handling strategy:
Result<T> / OneOf<T,E> boundaries, global exception handler for infrastructure faults
- DI registration: service lifetimes,
IOptions<T> bindings, module extension methods
- Test pyramid: unit / integration / contract test split;
WebApplicationFactory customisation plan
- Aspire AppHost (if distributed): resource declarations,
WithReference wiring, service defaults project
Step 4: Validate
Run the checklist below before handing off.
Validation
| Check | Pass Criteria |
|---|
| Target framework | net8.0 or net9.0; <LangVersion> pinned; <Nullable>enable</Nullable> |
| No .NET Framework | No net4x or netstandard targets in new projects |
| Result<T> boundaries | No try/catch for business logic branches in service layer |
| Constructor injection | No IServiceProvider.GetService in domain/application layers |
| EF Core reads | AsNoTracking() present on all read-only queries |
| EF Core hot paths | Compiled queries used for per-request lookups |
| Async hygiene | No .Result / .Wait(); CancellationToken propagated to all I/O |
| File-scoped namespaces | All new .cs files use file-scoped namespace declaration |
| Primary constructors | Used where no guard clauses or multi-overload logic is needed |
| NRT enabled | <Nullable>enable</Nullable>; no per-file suppressions without comment |
| Test coverage | xUnit unit tests + WebApplicationFactory integration tests present |
| Aspire scope | AppHost used for dev orchestration only; not wired to production runtime |
| Managed Identity | No connection strings or secrets inline in source or appsettings |
| NuGet hygiene | CPM (Directory.Packages.props) in place; packages.lock.json committed |
Handoff Protocol
## Handoff: dotnet-architect -> [next skill]
### Decisions Made
- API surface: [Minimal APIs / Web API / MVC] with rationale
- Data access: EF Core [8/9] with [SQL Server / PostgreSQL / DuckDB]; migration strategy: [migration bundles / ef database update]
- Error handling: Result<T> via [FluentResults / OneOf] at service boundary; global handler for infrastructure faults
- DI: constructor injection throughout; IOptions<T> for all configuration; module extension methods by concern
- Testing: xUnit + FluentAssertions + Verify; WebApplicationFactory for integration; Testcontainers for [DB / queue]
- Aspire: [yes/no]: AppHost wires [list resources]; service defaults project for telemetry
### Artifacts: Project layout diagram | API surface design | EF Core entity map | Test pyramid plan
### Open Questions: [items for azure-architect, identity-architect, security-architect, or next skill]
Sibling Skills
/identity-architect: Entra ID, B2C, Managed Identity provisioning, Conditional Access, RBAC role design
/security-architect: Defender for Cloud, Key Vault patterns, secret scanning, supply chain hardening
/iac-architect: Terraform/AVM modules that host this .NET workload
/azure-architect: Azure service selection, networking topology, WAF validation
/container-architect: AKS / Container Apps deployment when .NET app is containerised
/data-architect: Fabric / Databricks / lakehouse integration when EF Core is not the data layer
/ai-architect: Semantic Kernel / Azure OpenAI integration patterns within .NET apps
/agent: Pipeline orchestrator for cross-stack engagements