This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
All commands run from backend/.
# Build
dotnet build TaskManagement.sln
# Run API (requires SQL Server on localhost:1433)
dotnet run --project TaskManagement.Api
# Run all tests
dotnet test TaskManagement.sln --nologo
# Run a single test project
dotnet test TaskManagement.Domain.Tests --nologo
dotnet test TaskManagement.Api.Tests --nologo
# Run a single test by name filter
dotnet test TaskManagement.Domain.Tests --filter "FullyQualifiedName~Constructor_WithEmptyTitle"
# Apply EF Core migrations
dotnet ef database update --project TaskManagement.Infrastructure --startup-project TaskManagement.Api
# Add a new migration
dotnet ef migrations add <MigrationName> --project TaskManagement.Infrastructure --startup-project TaskManagement.ApiThe API starts at https://localhost:7xxx with Swagger UI at /swagger.
Database connection (SQL Server via Docker or localdb):
Server=localhost,1433;Database=TaskManagementDb;User Id=sa;Password=admin@123;TrustServerCertificate=True
Clean Architecture with four projects:
Domain → Application → Infrastructure
↘ Api ↙
- Domain —
TaskItementity,TaskItemStatus/TaskPriorityenums,DomainException/DomainValidationException. No external dependencies. All validation and domain rules live here. - Application —
ITaskItemService/TaskItemService,ITaskItemRepository(interface only), request/response DTOs (C# records). Depends on Domain only. - Infrastructure —
TaskManagementDbContext,TaskItemRepository, EF Core entity configuration, migrations, and 10-row seed data. Depends on Application. - Api —
TasksController,GlobalExceptionHandler, Swagger wiring. Depends on Application; references Infrastructure only for DI registration.
Domain model — TaskItem is a rich entity. Mutations go through named methods (UpdateDetails, ChangeStatus, ChangePriority, Reassign, SoftDelete). All mutators call EnsureNotDeleted() first and stamp ModifiedDate. Never set properties directly from outside the entity.
Soft delete — IsDeleted flag. EF Core global query filter on TaskManagementDbContext excludes deleted rows automatically. The DELETE /api/tasks/{id} endpoint calls SoftDelete(), not a database delete.
Exception → HTTP mapping — GlobalExceptionHandler (implements IExceptionHandler) maps domain exceptions:
DomainValidationException→ 400DomainException→ 409KeyNotFoundException→ 404- Default → 500
All error responses use the ErrorResponse record: { Status, Title, Detail, TraceId }.
Summary endpoint — GET /api/tasks/summary uses a raw SQL query (not EF) in TaskItemRepository.GetSummaryAsync() to return task counts grouped by status and priority.
Repository ordering — GetAllAsync orders results: Priority DESC → Status ASC → CreatedDate DESC.
Tests use NUnit 3 with [TestFixture] / [Test] / [TestCase]. The single test project TaskManagement.Domain.Tests covers only the Domain layer. Use Assert.Multiple when asserting several independent properties in one test.