✨ Updates API, C#, Docker, MSBuild, and Testing guidelines

Refines conventions for ASP.NET API endpoints, C# documentation,
Docker build arguments, MSBuild package management, and testing
method naming and structure. These changes aim to enhance clarity
and enforce best practices across the codebase.
This commit is contained in:
akritikos committed 2026-08-26 22:38:16 +03:00
1 parent b169a233ed
commit eea4ce7a0e
5 files changed
+21 -9

No files matched your search

@@ -10,11 +10,17 @@ description: "Use when writing API endpoints, routing, middleware, request/respo
## Endpoints ## Endpoints
- Prefer **Minimal APIs**; use Controllers only when the added structure is justified. - Prefer **Minimal APIs**; use Controllers only when the endpoint group requires action filters, model binding customisation, or exceeds 10 endpoints sharing significant cross-cutting logic.
- Group related endpoints using `MapGroup()` with a shared prefix and tag. - Group related endpoints using `MapGroup()` with a shared prefix and tag.
- Use **typed results** (`TypedResults.Ok()`, `TypedResults.NotFound()`) over untyped `Results` for OpenAPI metadata inference. - Use **typed results** (`TypedResults.Ok()`, `TypedResults.NotFound()`) over untyped `Results` for OpenAPI metadata inference.
- Return **`ProblemDetails`** (RFC 9457) for all error responses — configure via `AddProblemDetails()`. - Return **`ProblemDetails`** (RFC 9457) for all error responses — configure via `AddProblemDetails()`.
## Authorisation
- Apply `.RequireAuthorization()` at the group level for protected resources.
- Reference policy names through `const string` fields on a shared static class (e.g., `.RequireAuthorization(AuthorizationPolicies.RequireAdminRole)`) instead of inline string literals.
- Mark public endpoints explicitly with `.AllowAnonymous()`.
## Request Handling ## Request Handling
- Bind request data with **`[AsParameters]`** for complex parameter sets. - Bind request data with **`[AsParameters]`** for complex parameter sets.
+2 -3
View File
@@ -8,11 +8,10 @@ Code style is enforced by `.editorconfig`, `.globalconfig`, and StyleCop analyze
## Non-Obvious Defaults ## Non-Obvious Defaults
- XML doc comments required on public API in `src/` (suppressed in `tests/` and `samples/`). - XML doc comments required on all `public` and `protected` members in `src/` (suppressed in `tests/` and `samples/`).
- Avoid `null!` (null-forgiving operator) — fix the nullability flow instead of suppressing the warning. - Avoid `null!` (null-forgiving operator) — fix the nullability flow instead of suppressing the warning.
## Patterns ## Patterns
- Prefer **records** for DTOs, value objects, and other immutable data carriers. - Prefer **records** for DTOs, value objects, and other immutable data carriers.
- Use `LoggerMessage`-generated `partial` methods on a `partial class` — never log inline (e.g., `logger.LogInformation(…)`). - Use `LoggerMessage`-generated `partial` methods on a `partial class` — never log inline (e.g., `logger.LogInformation(…)`). If the containing type cannot be made `partial`, convert it to a `partial class` before adding logger methods. Do not fall back to inline logging.
+2 -2
View File
@@ -16,11 +16,11 @@ applyTo: "docker/**,compose*.yaml"
## Build Args ## Build Args
- `RUNTIME_BASE`: `web` (ASP.NET), `app` (console), or `self-contained` - `RUNTIME_BASE`: `web` (ASP.NET), `app` (console), or `self-contained`. If a use case does not match `web`, `app`, or `self-contained`, do not invent a new `RUNTIME_BASE` value — flag this to the user and ask which existing value best fits their scenario.
- `CONFIGURATION`: `Release` (default) or `Debug` - `CONFIGURATION`: `Release` (default) or `Debug`
- `PUBLISHED_PROJECT`: Project name to publish (without path or extension) - `PUBLISHED_PROJECT`: Project name to publish (without path or extension)
- `DATABASE_PROJECT`: EF Core project for migration bundles - `DATABASE_PROJECT`: EF Core project for migration bundles
- `DBCONTEXT`: Optional DbContext name for migrations - `DBCONTEXT`: Optional DbContext name for migrations. If omitted, the migration bundle step must not pass `--context`; EF Core auto-discovers the single DbContext in `DATABASE_PROJECT`.
## Image Selection ## Image Selection
+7 -1
View File
@@ -6,7 +6,9 @@ applyTo: "**/*.{csproj,props,targets}"
## Central Package Management ## Central Package Management
All package versions are declared in `Directory.Packages.props` at the repo root. In `.csproj` files: All package versions are declared in `Directory.Packages.props` at the repo root. In `Directory.Packages.props`, ensure the last child element of the root `<Project>` tag is `<Import Project="Directory.Packages.template.props" />`. `Directory.Packages.template.props` is **READ ONLY**, never edit it. The template provides default `<PackageVersion>` entries; any entry with the same `Include` declared earlier in `Directory.Packages.props` takes precedence over the template default, because MSBuild uses first-definition-wins semantics and the import appears last.
In `.csproj` files:
```xml ```xml
<!-- Correct --> <!-- Correct -->
@@ -22,6 +24,8 @@ To add or update a version, edit `Directory.Packages.props`:
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
``` ```
If the package does not exist in the template, simply add a new `<PackageVersion>` entry in `Directory.Packages.props`. No override logic is needed; the entry will be the sole definition.
## Properties Set Centrally (Do Not Override) ## Properties Set Centrally (Do Not Override)
These are configured in the root `Directory.Build.props` — do **not** set them in individual projects: These are configured in the root `Directory.Build.props` — do **not** set them in individual projects:
@@ -37,3 +41,5 @@ Handled automatically via `<InternalsVisibleToSuffix>` in the root props. Defaul
<InternalsVisibleTo Include="MyProject.IntegrationTests" /> <InternalsVisibleTo Include="MyProject.IntegrationTests" />
</ItemGroup> </ItemGroup>
``` ```
This is in addition to the automatically generated entries; do not remove or duplicate the default suffix entries.
+3 -2
View File
@@ -15,9 +15,10 @@ Build configuration is handled by `tests/Directory.Build.props` — do not resta
- Test project: `<ProjectUnderTest>.Tests` (matches InternalsVisibleTo default). - Test project: `<ProjectUnderTest>.Tests` (matches InternalsVisibleTo default).
- Test classes: `<ClassUnderTest>Tests`. - Test classes: `<ClassUnderTest>Tests`.
- Test methods: descriptive names — `MethodName_Condition_ExpectedResult` or similar. - Test methods: must use `MethodName_Condition_ExpectedResult` format. Example: `Add_NegativeNumbers_ThrowsArgumentException`.
## Structure ## Structure
- Follow **Arrange / Act / Assert**. - Follow **Arrange / Act / Assert**.
- Always propose a set of basic tests for new or changed code. - Always propose a set of basic tests for new or changed code. A basic test set must include at minimum: one happy-path test, one test per documented edge case or boundary condition, and one test for each expected exception.
- If no edge cases are explicitly documented, use judgment to identify and cover the most likely boundary conditions (e.g. null inputs, empty collections, zero/max values) and note the assumption in a comment.