SchoolAccount-CollectAPI is an API for the DfE School Account service built on .NET 10 based on this Api-Template. It provides a minimal clean architecture solution, with CQRS abstractions, structured logging, error handling, and architecture tests.
- Clean Architecture - layers, dependency rules, and code organisation
- Coding Standards - formatting, code analysis, naming, and style conventions
- Testing Standards - conventions and practices for writing tests
- Integration Testing - guidance on integration testing of the API endpoints
- Open API Documentation - guidance on adding Open API documentation to endpoints
Architecture decisions are recorded as ADRs in the decisions folder:
- Use Markdown Architectural Decision Records - why and how we record decisions
- Structure the solution using clean architecture - layers, dependency rules, and code organisation
- Strip the imported template to a minimal core - what was removed from the original template and why
- Run tests on the Microsoft Testing Platform - testing platform and how results and coverage are reported in CI
- Format code with CSharpier - why formatting is automated and enforced in the build
- Enforce code quality with Roslyn analysers - why SonarAnalyzer.CSharp and strict analysis are enforced in the build
- Validate requests with Data Annotations - why request shape is validated with Data Annotations rather than a FluentValidation decorator
New decisions should follow the ADR template.
Follow these steps to start the API locally.
Note: Windows users can use the git bash command prompt to run the project's .sh bash scripts.
-
Install prerequisites:
- .NET 10 SDK
- Docker Desktop
- Rider, Visual Studio, or Visual Studio Code
-
Run the setup script from the repository root to restore the dotnet tools and enable the git hooks:
./init.sh
-
Run the API using one of the following:
Method Command Outcome Docker Compose docker compose up --buildStarts the API and its dependencies (Seq) in containers .NET CLI dotnet run --project src/SchoolAccount.Collect.ApiRuns the API directly using the httplaunch profile, no containersIn Rider or Visual Studio you can use the equivalent
docker-composeorhttprun configurations from the toolbar.
Note: When running the application the messages No action descriptors found. may appear. This is a common message
for minimal APIs due to ASP.NET Core not being able to register controllers/endpoints.
-
Once running, the API is available at
http://localhost:5101:- Interactive API reference (Scalar) at
http://localhost:5101/scalar/v1 - Health checks at
http://localhost:5101/health - Logs (if started with compose) at
http://localhost:8081
The Scalar API reference is only mapped in the
Developmentenvironment. - Interactive API reference (Scalar) at
-
Debugging guidance:
- Set breakpoints in your C# files under
src/and start either run configuration with debugging enabled. .httpfiles alongside the endpoints insrc/SchoolAccount.Collect.Api/Endpointscan be used to exercise the API from your IDE.
- Set breakpoints in your C# files under
Use the .NET CLI to build or test the solution.
-
To build locally:
dotnet build
-
To run all tests:
dotnet test
Architecture tests under tests/SchoolAccount.Collect.ArchitectureTests enforce the clean architecture dependency rules between layers.
Code is formatted with CSharpier, installed as a local dotnet tool and enforced by the "Check formatting" step in the build workflow. To format the solution locally:
dotnet csharpier format .A pre-commit hook, managed by Husky.NET and configured in .husky/task-runner.json, formats staged C# files automatically before each commit; init.sh installs it and restores the tools on a fresh clone. To format on save, install the Rider plugin or the VS Code extension; the editors documentation covers setup for these and other IDEs. See Format code with CSharpier for the reasoning.
The build runs with the full set of .NET/Roslyn analyzers (AnalysisLevel=latest, AnalysisMode=All) plus
SonarAnalyzer.CSharp, configured in
Directory.Build.props. TreatWarningsAsErrors means any violation fails dotnet build,
locally and in the build workflow, rather than being left as a warning. Rules that
don't fit this codebase are suppressed by ID in .editorconfig. See
Coding Standards and
Enforce code quality with Roslyn analysers for the
conventions and the reasoning.
The build workflow collects code coverage on every run, posts a summary to the pull
request, and fails the build if line coverage drops below the minimum threshold. The threshold is defined by the
MIN_LINE_COVERAGE variable at the top of build.yml. Which files are included is
controlled by coverage.config.
To generate the same report locally, run coverage.sh from the repository root:
./coverage.shThe script runs all tests with coverage enabled, merges the per-project results with ReportGenerator, and writes an
HTML report to TestResults/CoverageReport/index.html. Pass --open to open the report in your browser when it
finishes:
./coverage.sh --openThe solution follows a clean architecture pattern with vertical slice features:
| Project | Purpose |
|---|---|
SchoolAccount.Collect.Api |
ASP.NET Core Web API - endpoints, middleware, error handling |
SchoolAccount.Collect.Application |
CQRS handlers and feature logic, organised by feature folder |
SchoolAccount.Collect.Domain |
Domain entities and business rules |
SchoolAccount.Collect.Infrastructure |
External concerns - time, data access, integrations |
SchoolAccount.Collect.SharedKernel |
Shared primitives - Result<T>, Error, ValidationError |
Each endpoint implements IEndpoint and is discovered and mapped automatically at startup. See
Structure the solution using clean architecture for the dependency rules.
Structured logs are written via Serilog to Seq. When running via Docker Compose, the Seq UI is available at http://localhost:8081.
- Branch from
mainusing the conventiontask/<short-description>orfeature/<short-description>. - Open a pull request against
main. - The build workflow must pass before merging.