This repository is an ASP.NET Core modular monolith template.
src/ProjectName.Hostis the composition root. Keep it focused on middleware, service registration, endpoint mapping, and host configuration.src/Product/Modules/{ModuleName}contains product modules.src/Librariescontains portable libraries that can move between projects.src/Product/Sharedcontains product-owned stable cross-module building blocks and conventions.src/RootInfrastructure/ProjectName.Persistencecontains application-level persistence composition, database initialization, and cross-DbContext transactions.testsmirrors the product/module layout.- Project documentation starts at
docs/README.md; update it when architecture, module boundaries, persistence ownership, authentication behavior, or public API conventions change.
Each module follows this layout:
{ModuleName}.Contracts/
Core/
|-- {ModuleName}.Domain/
`-- {ModuleName}.Application/
Adapters/
|-- {ModuleName}.Infrastructure/
`-- {ModuleName}.Presentation/
Domaincontains entities, aggregates, domain errors/events, domain services, and repository contracts.Applicationcontains use cases, MediatR handlers, validators, and module-specific ports.Contractscontains stable module APIs for other modules. Do not put HTTP models, EF Core entities, Identity types, or provider-specific errors here.Infrastructurecontains EF Core, repository implementations, external adapters, Identity integration, and read projections.Presentationcontains Minimal API endpoint mapping and HTTP request/response models.- Modules may talk to other modules through
Contractsprojects only. - Do not reference another module's
Domain,Application,Infrastructure, orPresentationproject from a module.
- Keep business logic out of
ProjectName.Hostand endpoint handlers. - Keep EF Core, ASP.NET Core Identity, provider SDKs, and transport concerns out of domain/application code.
- Return
ResultorResult<T>for business failures; reserve exceptions for technical failures and programming errors. - Use shared building blocks only for generic, stable concepts that are genuinely shared across modules.
- Keep
CancellationTokenparameter names asct. - Prefer existing folder conventions and registration patterns over new abstractions.
- Keep NuGet package versions in
Directory.Packages.props; project files should usePackageReferencewithoutVersion. - Keep shared MSBuild policy in
Directory.Build.props; do not duplicate common properties in individual project files. - Do not disable nullable, analyzers, or code-style enforcement in a project file without documenting why.
- When changing package references or central package versions, run a vulnerability audit.
- Do not add build outputs, IDE state, user-local files, logs, coverage output, or temporary files to the repository.
*.CoreTestscover domain and application behavior.*.IntegrationTestscover infrastructure, persistence, or HTTP-level behavior.ProjectName.ArchitectureTestscovers solution-level dependency and naming rules.- Add focused tests for changes to domain invariants, auth/authorization, refresh-token rotation, module contracts, persistence mappings, migrations, error mapping, cross-module workflows, or architecture boundaries.
Run the relevant checks before handing off:
dotnet restore .\ProjectName.slnx
dotnet build .\ProjectName.slnx --no-restore
dotnet test .\ProjectName.slnx --no-build
dotnet list .\ProjectName.slnx package --vulnerable --include-transitiveIf a command cannot be run, state that explicitly with the reason.