22
33These instructions guide GitHub Copilot on how to assist meaningfully within this repository.
44
5- ## 🎯 Project Overview
5+ ## 🔭 Project Overview
66
7- This project is a proof-of-concept Web API built using:
7+ This project is a proof-of-concept RESTful Web API built using:
88- ** .NET 8 (LTS)**
9- - ** ASP.NET Core**
10- - ** EF Core** with a ** SQLite** database for simplicity
11- - ** Docker Compose** for basic containerization
9+ - ** ASP.NET Core 8.0 **
10+ - ** EF Core 9.0 ** with ** SQLite 3 ** database
11+ - ** Docker Compose** for containerization
1212
1313### Key Characteristics
1414- ** Purpose** : Learning-focused PoC demonstrating modern ASP.NET Core patterns
1515- ** Complexity** : Simple CRUD operations with a single ` Player ` entity
16- - ** Focus** : Clean architecture, best practices, and maintainable code
17- - ** Database** : SQLite for development; PostgreSQL may be introduced later
16+ - ** Focus** : Layered architecture, best practices, and maintainable code
17+ - ** Database** : SQLite (dev); PostgreSQL planned for later
18+ - ** Pattern** : Repository Pattern + Service Layer + AutoMapper + FluentValidation
1819
19- ## ✅ Coding Conventions
20+ ## 📐 Coding Conventions
2021
2122Follow standard C# conventions:
22- - Use ` PascalCase ` for class names, methods, and public properties
23- - Use ` camelCase ` for local variables and private fields
24- - Use ` async/await ` consistently for asynchronous code
25- - Prefer ` var ` for local variable declarations where the type is obvious
26- - Nullable reference types are ** enabled**
27- - Use ` CSharpier ` formatting standards (opinionated)
23+ - ** PascalCase** : Class names, methods, public properties
24+ - ** camelCase** : Local variables, private fields
25+ - ** Primary constructors** : Used throughout (controllers, services, repositories, middleware)
26+ - ** async/await** : All I/O operations are asynchronous
27+ - ** var** : Preferred for local variables when type is obvious
28+ - ** Nullable reference types** : Enabled project-wide
29+ - ** CSharpier** : Code formatter (opinionated style)
30+ - ** XML docs** : Enabled for API documentation (NoWarn 1591 suppresses warnings)
2831
2932## 🏗️ Architectural Patterns
3033
3134This project follows a ** layered architecture** with clear separation of concerns:
3235
3336### Layer Structure
34- - ** Controllers** (` /Controllers ` ) - Handle HTTP requests and responses
35- - ** Services** (` /Services ` ) - Contain business logic and orchestration
36- - ** Repositories** (` /Repositories ` ) - Abstract data access layer
37+ - ** Controllers** (` /Controllers ` ) - Handle HTTP requests/responses, route to services
38+ - ** Services** (` /Services ` ) - Business logic, caching, orchestration
39+ - ** Repositories** (` /Repositories ` ) - Data access abstraction (generic base + specific)
3740- ** Models** (` /Models ` ) - Domain entities and DTOs
3841 - ` Player ` - Core domain entity
39- - ` PlayerRequestModel ` - Input validation model
40- - ` PlayerResponseModel ` - API response model
42+ - ` PlayerRequestModel ` - Input validation model (used by FluentValidation)
43+ - ` PlayerResponseModel ` - API response model (mapped by AutoMapper)
4144- ** Validators** (` /Validators ` ) - FluentValidation rules
42- - ** Mappings** (` /Mappings ` ) - AutoMapper configurations
43- - ** Data** (` /Data ` ) - EF Core DbContext and database concerns
45+ - ** Mappings** (` /Mappings ` ) - AutoMapper profiles
46+ - ** Data** (` /Data ` ) - EF Core DbContext and database configuration
47+ - ** Middlewares** (` /Middlewares ` ) - Custom middleware (exception handling)
48+ - ** Extensions** (` /Extensions ` ) - Service registration and middleware extension methods
49+ - ** Configurations** (` /Configurations ` ) - Swagger and rate limiter configurations
4450
4551### Design Principles
46- - ** Dependency Injection** for all services and repositories
47- - ** Repository Pattern** for data access abstraction
48- - ** Service Layer** for business logic encapsulation
49- - ** AutoMapper** for clean object transformations
50- - ** FluentValidation** for robust input validation
51- - ** Async/Await** throughout the application stack
52+ - ** Dependency Injection** : All services, repositories, validators registered in DI container
53+ - ** Repository Pattern** : Generic base ` Repository<T> ` + specific ` PlayerRepository ` with custom queries
54+ - ** Service Layer** : Business logic, caching, and orchestration (separated from controllers)
55+ - ** AutoMapper** : Request/Response model transformations (bidirectional mapping)
56+ - ** FluentValidation** : Input validation (structure/format in validators, business rules in services)
57+ - ** Async/Await** : All I/O operations use async patterns (database, cache)
58+ - ** Extension Methods** : Service registration grouped in ` ServiceCollectionExtensions ` by concern
59+ - ** Global Exception Handling** : ` ExceptionMiddleware ` with RFC 7807 Problem Details format
5260
5361## ✅ Copilot Should Focus On
5462
55- - Generating idiomatic ASP.NET Core controller actions
56- - Writing EF Core queries using LINQ
57- - Following async programming practices
58- - Producing unit tests using ** xUnit**
59- - Suggesting dependency-injected services
63+ - Generating idiomatic ASP.NET Core controller actions with minimal logic
64+ - Writing EF Core queries using LINQ with ` AsNoTracking() ` for read operations
65+ - Following async programming practices consistently
66+ - Producing unit tests using ** xUnit** with ** Moq ** and ** FluentAssertions **
67+ - Suggesting dependency-injected services using primary constructors
6068- Adhering to RESTful naming and HTTP status codes
61- - Using ` ILogger<T> ` for logging
62- - Working with Docker-friendly patterns
63- - Implementing proper error handling and validation
64- - Using appropriate HTTP status codes (200, 201, 400, 404, 409, etc. )
69+ - Using ` ILogger<T> ` for structured logging with meaningful context
70+ - Working with Docker-friendly patterns (volume persistence, health checks)
71+ - Implementing proper error handling with RFC 7807 Problem Details
72+ - Using appropriate HTTP status codes (200, 201, 400, 404, 409, 500 )
6573- Following the existing caching patterns with ` IMemoryCache `
74+ - Using extension methods to organize service registration by domain area
75+ - Implementing validation with FluentValidation for structure, service layer for business rules
6676
6777## 🚫 Copilot Should Avoid
6878
6979- Generating raw SQL unless explicitly required
7080- Using EF Core synchronous APIs (e.g., ` FirstOrDefault ` over ` FirstOrDefaultAsync ` )
7181- Suggesting static service or repository classes
72- - Including XML comments or doc stubs unless requested
82+ - Including verbose XML comments or doc stubs unless requested
7383- Suggesting patterns that conflict with DI (e.g., ` new Service() ` instead of constructor injection)
74- - Using ` ConfigureAwait(false) ` in ASP.NET Core contexts
84+ - Using ` ConfigureAwait(false) ` in ASP.NET Core contexts (not needed)
7585- Implementing complex inheritance hierarchies when composition is simpler
7686- Adding unnecessary middleware or filters without clear purpose
87+ - Creating controller logic that belongs in services (fat controllers)
88+ - Mixing async and sync code patterns inconsistently
7789
7890## 🧪 Testing
7991
8092- Use ** xUnit** with ` [Fact] ` and ` [Theory] ` attributes
81- - Use ** Moq** for mocking
93+ - Use ** Moq** for mocking dependencies
94+ - Use ** FluentAssertions** for readable test assertions
8295- Prefer testing ** service logic** and ** controller behavior**
8396- Place unit tests under ` test/ ` following structure already present (e.g., ` Unit/PlayerServiceTests.cs ` )
8497- ** Test Naming** : Follow ` Given_When_Then ` pattern (e.g., ` GivenCreateAsync_WhenRepositoryAddAsync_ThenAddsPlayerToRepositoryAndRemovesCache ` )
8598- ** Test Structure** : Use Arrange, Act, Assert comments to organize test code
8699- ** Test Attributes** : Add ` [Trait("Category", "Unit")] ` to all unit tests
87- - ** Test Data** : Use faker patterns for consistent test data generation
88- - ** Assertions** : FluentAssertions for readable test assertions
100+ - ** Test Data** : Use faker patterns for consistent test data generation (see ` PlayerFakes ` utility)
101+ - ** Mocking Setup** : Use ` PlayerMocks.InitServiceMocks() ` pattern for consistent mock initialization
102+ - ** Verify Calls** : Always verify repository/service interactions with ` Times.Once ` or appropriate multiplicity
89103
90104## ⚡ Performance & Best Practices
91105
92- - Use ` AsNoTracking() ` for read-only EF Core queries
106+ - Use ` AsNoTracking() ` for read-only EF Core queries (already implemented in Repository base class)
93107- Implement caching patterns with ` IMemoryCache ` for frequently accessed data
94- - Use ` DbContextPool ` for better performance (already configured)
95- - Follow async/await patterns consistently
108+ - Cache TTL: Sliding expiration (10 min) + absolute expiration (1 hour)
109+ - Cache invalidation: Remove cache on data modifications
110+ - Use ` AddDbContextPool<T>() ` for better performance (already configured)
111+ - Follow async/await patterns consistently throughout the stack
96112- Validate input using ** FluentValidation** before processing
97- - Use AutoMapper for object transformations
98- - Implement proper logging with structured logging patterns
113+ - Use AutoMapper for object transformations (avoid manual mapping)
114+ - Implement proper logging with structured logging patterns using Serilog
115+ - Use primary constructors for DI to reduce boilerplate
116+ - Group service registration in extension methods by domain area (see ` ServiceCollectionExtensions ` )
99117
100- ## 🔧 Tooling & Environment
118+ ## 🛠 Tooling & Environment
101119
102120- Format code with ** CSharpier**
103121- SQLite is used in development; ** PostgreSQL** may be introduced in production later
104122- Code runs in a ** Docker Compose** environment
105123- .NET 8 SDK is required
106124- All configurations live in ` appsettings.*.json ` files
107125
108- ## 🏷️ Technology Stack Deep Dive
126+ ## 📚 Technology Stack Deep Dive
109127
110128### Entity Framework Core
111129- ** DbContext** : ` PlayerDbContext ` with SQLite provider
@@ -117,26 +135,27 @@ This project follows a **layered architecture** with clear separation of concern
117135### AutoMapper
118136- ** Profile** : ` PlayerMappingProfile ` handles all object mappings
119137- ** Bidirectional** : Maps between request/response models and entities
120- - ** Integration** : Registered in DI container
138+ - ** Integration** : Registered in DI container via ` AddMappings() ` extension
121139
122140### FluentValidation
123141- ** Validators** : ` PlayerRequestModelValidator ` for input validation
124142- ** Integration** : Automatic validation in controllers before processing
125- - ** Error Messages** : Descriptive validation messages
143+ - ** Error Messages** : Descriptive validation messages with property names
126144
127145### Caching Strategy
128146- ** IMemoryCache** : Service-level caching for read operations
129- - ** Cache Keys** : Consistent naming with ` nameof() ` pattern
130- - ** Invalidation** : Cache cleared on data modifications
147+ - ** Cache Keys** : Consistent naming with ` nameof() ` pattern (e.g., ` nameof(RetrieveAsync) ` )
148+ - ** Invalidation** : Cache cleared on data modifications via ` Remove(CacheKey) `
131149- ** TTL** : Sliding expiration (10 min) + absolute expiration (1 hour)
132150
133151### Logging with Serilog
134- - ** Structured Logging** : Consistent log message templates
152+ - ** Structured Logging** : Consistent log message templates with ` {@Property} ` for object serialization
135153- ** Log Levels** : Appropriate use of Information, Warning, Error
136- - ** Context** : Include relevant data in log messages
137- - ** Configuration** : File and console sinks configured
154+ - ** Context** : Include relevant data in log messages (e.g., player IDs, squad numbers)
155+ - ** Configuration** : File and console sinks configured in ` appsettings.json `
156+ - ** Output** : Logs to ` logs/log-<date>.log ` and console with custom templates
138157
139- ## 🧩 Folder Conventions
158+ ## 🗂 Folder Conventions
140159
141160- ` Controllers ` for Web API endpoints
142161- ` Services ` for business logic
@@ -150,7 +169,7 @@ This project follows a **layered architecture** with clear separation of concern
150169
151170Keep things ** simple, clear, and idiomatic** . This is a learning-focused PoC — clarity and maintainability win over overengineering.
152171
153- ## 📋 Common Patterns in This Codebase
172+ ## 🧭 Common Patterns in This Codebase
154173
155174### Repository Pattern
156175``` csharp
@@ -173,7 +192,7 @@ public class PlayerRepository : Repository<Player>, IPlayerRepository
173192``` csharp
174193public class PlayerService : IPlayerService
175194{
176- // Dependencies injected via constructor
195+ // Dependencies injected via primary constructor
177196 // Business logic with caching
178197 // AutoMapper for transformations
179198 // Logging for observability
@@ -193,7 +212,19 @@ public class PlayerController : ControllerBase
193212 }
194213```
195214
196- ## 🎯 Domain Knowledge
215+ ### Exception Middleware Pattern
216+ ``` csharp
217+ // Global exception handling with RFC 7807 Problem Details
218+ public class ExceptionMiddleware (RequestDelegate next , ILogger <ExceptionMiddleware > logger , IHostEnvironment environment )
219+ {
220+ // Maps exceptions to appropriate HTTP status codes
221+ // Returns standardized problem details JSON
222+ // Includes stack traces in development only
223+ }
224+ ```
225+
226+
227+ ## 💡 Domain Knowledge
197228
198229### Player Entity Context
199230- ** Squad Numbers** : Must be unique (1-99 typically)
@@ -231,7 +262,7 @@ return player; // Let caller handle null
2312623 . ** Caching** : Service layer implements ` IMemoryCache ` for read operations
2322634 . ** Logging** : Structured logging at each layer for observability
233264
234- ## 🎯 When to Use Different Approaches
265+ ## 🤔 When to Use Different Approaches
235266
236267### Choose EF Core When:
237268- Simple CRUD operations (current use case)
@@ -253,7 +284,7 @@ return player; // Let caller handle null
253284- Use route parameters for resource identification
254285- Apply validation before processing requests
255286
256- ## 🛠 ️ Essential Commands & Workflows
287+ ## ⌨ ️ Essential Commands & Workflows
257288
258289### Build & Run
259290``` bash
@@ -337,7 +368,7 @@ docker compose down -v
337368- Default: 60 requests per 60 seconds (fixed window)
338369- Queue limit: 0 (immediate rejection when limit reached)
339370
340- ## 🚨 Common Issues & Workarounds
371+ ## 🔧 Common Issues & Workarounds
341372
342373### Database Path Issues
343374- ** Development** : ` storage/players-sqlite3.db ` (source, copied to ` bin/Debug/net8.0/storage/ ` during build)
@@ -381,6 +412,5 @@ See open issues on GitHub for planned enhancements:
381412- ** PostgreSQL Support** ([ #249 ] ( https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/issues/249 ) ) - Add PostgreSQL to Docker Compose setup
382413- ** .NET Aspire Integration** ([ #256 ] ( https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/issues/256 ) ) - Evaluate Aspire for dev-time orchestration and observability
383414- ** JWT Authentication** ([ #105 ] ( https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/issues/105 ) ) - Implement Client Credentials Flow for protected routes
384- - ** Global Exception Handling** ([ #184 ] ( https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/issues/184 ) ) - Add middleware with RFC 7807 Problem Details
385415- ** Optimistic Concurrency** ([ #65 ] ( https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/issues/65 ) ) - Handle conflicts with application-managed tokens
386416- ** Database Normalization** ([ #125 ] ( https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/issues/125 ) ) - Extract Position, Team, League into separate tables
0 commit comments