Instruction file imported from Xizt/proxy-llmservice (
.cursor/rules/backend-context.mdc). Copyright stays with the author.
description: .NET layered backend, API, and database standards globs: **/*.cs
You are an expert in .NET, ASP.NET Core, C#, Entity Framework Core, and layered backend architecture.
Architecture Overview
The backend follows a layered architecture with clear separation of concerns:
- Server — API controllers and server configuration
- BusinessLayer — Business logic and service implementations
- Models — DTOs for requests and responses
- DataLayer — Data access, entity models, and database context
- Common — Shared utilities and constants
Project Structure
Server
- Controllers/ — API endpoints organized by domain
- Program.cs — Application configuration, dependency injection, and middleware
- appsettings.json — Environment-specific configuration
BusinessLayer
- Auth/ — Authentication services and providers
- Common/ — Business-specific shared utilities
- Extensions/ — Extension methods
Models
- Request/ — Incoming API request DTOs
- Response/ — Outgoing API response DTOs
- Common/ — Shared model definitions
- Auth/ — Authentication-related models
DataLayer
- Models/ — Entity definitions mapped to database tables
- Migrations/ — EF Core migrations
- Common/ — Data access utilities
Common
- Shared utilities and constants used across all projects
Code Organization
- One class per file with a matching filename.
- Namespaces reflect project and folder structure.
- Group related files in domain-specific folders.
- Enable and respect nullable reference types project-wide.
- Prefer
recordtypes for immutable DTOs and value objects. - Use
IReadOnlyList/IReadOnlyCollectionfor return types when callers should not mutate results.
Documentation
- Add XML comments to all public members, classes, and methods.
- Include summary blocks and parameter documentation.
- Document return values, including null and empty-collection edge cases.
Dependency Injection
- Define services behind interfaces (e.g.
IAuthService). - Inject dependencies through constructors.
- Register services with appropriate lifetimes in
Program.cs. - Use Singleton for stateless services, Scoped for per-request services (e.g.
DbContext), and Transient only when a fresh instance is genuinely needed. - Never resolve services manually from
IServiceProviderinside business logic.
Entity Design
- All database entities inherit from
BaseEntity. - Include audit fields: created/modified timestamps and user tracking.
- Define clear navigation properties and relationships.
Error Handling
- Use centralized exception-handling middleware for unhandled exceptions.
- Return Problem Details (RFC 7807) with type, title, status, detail, and instance.
- Define custom domain exceptions (e.g.
NotFoundException,ConflictException) for expected business rule violations. - For expected failures such as validation, prefer a result object over throwing exceptions.
- Use guard clauses at method entry.
- Never return stack traces, internal paths, or raw database errors in API responses.
- Log exceptions with full context (correlation ID, user, operation).
Logging
- Inject
ILogger<T>(or Serilog) into every service. - Use log levels intentionally: Debug, Information, Warning, Error, Critical.
- Use structured message templates with named parameters instead of string interpolation.
- Propagate a correlation/request ID through the request pipeline.
- Never log passwords, tokens, API keys, PII, or sensitive request bodies.
API Design
- Use RESTful endpoints with clear route attributes.
- Keep controllers thin; return appropriate action results.
- Use DTOs for request/response instead of exposing entities.
- Use correct HTTP status codes: 200, 201 (with Location), 204, 400, 401, 403, 404, 409, 500.
- Paginate all list endpoints; never return unbounded collections.
- Version APIs to allow non-breaking evolution.
- Maintain Swagger/OpenAPI docs with
ProducesResponseTypefor all status codes. - Use a consistent response envelope (e.g.
{ data, errors, meta }). - Make PUT and DELETE idempotent; consider idempotency keys for POST where appropriate.
Input Validation & Sanitization
- Use data annotations on request DTOs (
Required,MaxLength,Range,RegularExpression, etc.). - Use FluentValidation with one validator class per request DTO for complex rules.
- Validate
ModelStatein controllers (or via a filter) and return 400 with detailed errors. - Sanitize user inputs to prevent XSS.
- Prefer whitelists (enums, known values) over blacklists.
Authentication & Authorization
- Use JWT tokens and claims-based identity.
- Support external authentication providers where needed.
- Apply
[Authorize]and policy/role-based authorization; default to requiring authentication. - Follow least privilege.
- Use short-lived access tokens with refresh token rotation.
- Never hardcode secrets; use User Secrets in development and a vault in production.
Security
- Enforce HTTPS in production; use HSTS.
- Configure CORS with explicit allowed origins; never use
*in production. - Apply rate limiting on public and authentication endpoints.
- Use anti-forgery tokens for form-based endpoints where applicable.
- Set security headers:
X-Content-Type-Options,X-Frame-Options,Content-Security-Policy,Referrer-Policy. - Scan NuGet dependencies for known vulnerabilities.
Performance
- Never block on async code with
.Resultor.Wait(); propagateasync/awaitthrough the call chain. - Accept and pass
CancellationTokenin all async methods. - Use
IMemoryCachefor frequently accessed, rarely changing data; use distributed cache for multi-instance deployments. - Enable response compression for text-based payloads.
- Select only needed columns; use projections instead of loading full entities when possible.
- Prefer explicit eager loading (
Include/ThenInclude) or projection over lazy loading.
Service Layer Guidelines
- Return result objects (e.g.
ServiceResult<T>) for success/failure instead of relying solely on exceptions. - Do not depend on
HttpContextor ASP.NET-specific types in business services; pass required data as parameters. - Design service methods to be safely retried where possible.
- Define transaction scope at the service layer, not in repositories or controllers.
Best Practices
- Do not reference DataLayer directly from Controllers.
- Avoid static methods; use dependency injection.
- Keep business logic in services, not controllers.
- Follow naming conventions:
- Interfaces prefixed with
I(e.g.IAuthService) - DTOs suffixed with
Dto(e.g.UserDto) - Controllers suffixed with
Controller - Async methods suffixed with
Async
- Interfaces prefixed with
- Bind configuration sections to classes using the Options pattern.
- Write integration tests with
WebApplicationFactory. - Dispose resources with
usingorIAsyncDisposable. - Use
IHttpClientFactory; never instantiateHttpClientdirectly.
Database Practices
- Use EF Core code-first with migrations.
- Use soft deletes via an
IsDeletedflag. - Track audit trails for creation and modification.
- Use transactions for operations that modify multiple entities.
- Avoid N+1 queries; use
Include/ThenIncludeand profile queries during development. - Add indexes on columns used in WHERE, JOIN, and ORDER BY clauses.
- Always use parameterized queries or EF Core LINQ; never concatenate user input into raw SQL.
- Write idempotent migrations; use
IF NOT EXISTSchecks in raw SQL migrations. - Rely on EF Core connection pooling.
- Seed reference/lookup data via
HasDataor a dedicated seeding service.
Verification
- Verify changes by building the server project before finishing.