-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdotnet-csharp.mdc
More file actions
128 lines (96 loc) · 7.57 KB
/
Copy pathdotnet-csharp.mdc
File metadata and controls
128 lines (96 loc) · 7.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
---
description: C# ASP.NET Core rules — async Task, cancellation tokens, UTC dates, no logic in controllers.
globs: ""
alwaysApply: true
---
## Async and Threading
- Never write `async void`. Only `async Task` or `async Task<T>`. Exception: event handlers in UI code only.
- Every async method must accept `CancellationToken cancellationToken` as the last parameter and pass it to all downstream async calls.
- Never call `.Result`, `.Wait()`, or `.GetAwaiter().GetResult()` on Tasks. Use `await` instead.
- Never use `Task.Run()` in ASP.NET Core handlers. Use `await` directly on I/O-bound operations.
- Never use `ConfigureAwait(false)` in library code — it's implicit in ASP.NET Core context.
## DateTime and Time
- Use `DateTime.UtcNow` exclusively. Never `DateTime.Now`.
- Use `DateTimeOffset.UtcNow` for APIs that need timezone awareness.
- Never hardcode timezone offsets. Use `TimeZoneInfo.FindSystemTimeZoneById()` if conversion is required.
- All timestamps in databases must be stored as UTC. Document this in migration comments.
## Controller and Endpoint Structure
- Controllers must be in `src/Features/{FeatureName}/Controllers/{FeatureName}Controller.cs`.
- Controllers are routing and validation only. Zero business logic. Delegate to service layer immediately.
- Every controller action must return `IActionResult` or `ActionResult<T>`, never `object`.
- Every POST/PUT/PATCH endpoint must validate input with `if (!ModelState.IsValid) return BadRequest(ModelState)` before calling services.
- Controller actions must not catch exceptions. Let middleware handle them.
## Service Layer
- Services must be in `src/Features/{FeatureName}/Services/{FeatureName}Service.cs`.
- Services contain all business logic. Controllers call services. Services call repositories.
- Service methods must be `public async Task<T>` or `public async Task`, never `public T` (synchronous).
- Every service method that performs I/O must accept `CancellationToken cancellationToken`.
- Services must not reference `HttpContext` or any HTTP types. Inject dependencies instead.
## Repository and Data Access
- Repositories must be in `src/Data/Repositories/{EntityName}Repository.cs`.
- Repositories are data access only. No business logic. No validation beyond null checks.
- Every repository method must accept `CancellationToken cancellationToken` and pass it to EF Core.
- Never use `.ToList()` or `.ToArray()` without `await`. Use `await query.ToListAsync()`.
- Never use LINQ to Objects on database queries. Move `.Where()` and `.Select()` before `.ToListAsync()`.
## Dependency Injection
- All dependencies must be registered in `Program.cs` in the `services.Add*()` section.
- Use `services.AddScoped<IService, Service>()` for services. Never `AddSingleton` for stateful services.
- Use `services.AddTransient<IFactory>()` only for factories. Never for services.
- Never use `ServiceLocator` pattern. Inject dependencies into constructors.
- Constructor parameters must be private readonly fields. No public properties for injected dependencies.
## Error Handling
- Create custom exception types in `src/Exceptions/{FeatureName}Exception.cs`. Never throw `Exception` or `ApplicationException`.
- Every custom exception must inherit from `ApplicationException` and include a `public string ErrorCode { get; }` property.
- Catch exceptions only at middleware level in `Program.cs` or in a global exception handler middleware.
- Never catch and swallow exceptions silently. Log them with `ILogger<T>.LogError(ex, "message")` before re-throwing.
- Validation errors must throw `ValidationException` with a list of field errors, not generic exceptions.
## Input Validation
- All user input must be validated at the controller boundary using `[Required]`, `[StringLength]`, `[Range]` attributes.
- Complex validation logic must be in a separate `Validators/{EntityName}Validator.cs` using FluentValidation.
- Never trust query parameters, headers, or form data. Validate everything before passing to services.
- File uploads must validate MIME type, size, and filename. Never trust `Content-Type` header alone.
## Configuration and Secrets
- Never hardcode connection strings, API keys, or credentials in code.
- All configuration must come from `appsettings.json`, `appsettings.{Environment}.json`, or environment variables.
- Secrets must be in `User Secrets` (development) or Azure Key Vault (production). Never in version control.
- Configuration classes must be in `src/Configuration/{FeatureName}Options.cs` and bound with `services.Configure<T>()`.
## Naming Conventions
- Classes: PascalCase. Interfaces: `IPascalCase`. Private fields: `_camelCase`. Local variables: `camelCase`.
- Async methods must end with `Async`. Example: `GetUserAsync()`, never `GetUser()`.
- Boolean properties must start with `Is`, `Has`, `Can`, or `Should`. Example: `IsActive`, `HasPermission`.
- Constants must be `UPPER_SNAKE_CASE` and `public static readonly`.
- File names must match class names exactly. `UserService.cs` contains `public class UserService`.
## File Structure
- Root directories: `src/`, `tests/`, `docs/`.
- `src/` contains: `Features/`, `Data/`, `Configuration/`, `Exceptions/`, `Middleware/`, `Extensions/`.
- Each feature in `src/Features/{FeatureName}/` contains: `Controllers/`, `Services/`, `Models/`, `Validators/`.
- `Models/` contains DTOs and request/response types only. Never domain entities.
- `tests/` mirrors `src/` structure with `.Tests` suffix on project names.
## Testing
- Unit tests must be in `tests/{FeatureName}.Tests/Services/{FeatureName}ServiceTests.cs`.
- Integration tests must be in `tests/{FeatureName}.Tests/Integration/{FeatureName}ControllerTests.cs`.
- Test class names must end with `Tests`. Test methods must start with `Should_` or `When_`.
- Every service method must have at least one happy-path test and one error-case test.
- Mock external dependencies with Moq. Never mock repositories in service tests — use in-memory database.
- Test async methods with `[Fact] public async Task MethodName_ReturnsExpected()`.
## Logging
- Inject `ILogger<T>` into every service and controller. Never use static loggers.
- Log at appropriate levels: `LogInformation()` for business events, `LogWarning()` for recoverable issues, `LogError()` for exceptions.
- Never log sensitive data (passwords, tokens, PII). Use `{UserId}` placeholders instead.
- Always include exception details: `_logger.LogError(ex, "Operation failed for {UserId}", userId)`.
## Security
- Never use `[AllowAnonymous]` on endpoints. Require explicit `[Authorize]` or role-based `[Authorize(Roles = "Admin")]`.
- Validate authorization in services, not just controllers. Check user permissions before data access.
- Use parameterized queries exclusively. Never string concatenation in SQL or LINQ.
- Hash passwords with `BCrypt.Net-Core`. Never store plaintext passwords.
- Sanitize all user input before storing or displaying. Use `System.Net.WebUtility.HtmlEncode()` for HTML output.
## Entity Framework Core
- DbContext must be in `src/Data/{ProjectName}DbContext.cs`.
- Entity configurations must be in `src/Data/Configurations/{EntityName}Configuration.cs` using `IEntityTypeConfiguration<T>`.
- Never use `HasData()` for seed data. Use a separate migration or seeding service.
- Always use `[Timestamp]` attribute on concurrency columns. Never manual version handling.
- Foreign keys must be explicitly configured with `.HasForeignKey()` and `.OnDelete()` cascade rules.
---
> Source: [Codelibrium](https://codelibrium.com) — the marketplace for AI behaviour files.
> Browse multiple rulesets at [codelibrium.com](https://codelibrium.com) or install via CLI:
> `npx codelibrium-cli install <ruleset-name>`