Instruction file imported from fkucukkara/result-pattern (
.github/instructions/result-pattern.instructions.md). Copyright stays with the author.
Result Pattern Instructions
Core Pattern
This project uses the Result Pattern to make failures explicit in method signatures instead of throwing exceptions for expected error cases.
Result Type
- Use
Result<T>.Success(value)for successful outcomes - Use
Result<T>.Failure("message")for expected failures (validation, not-found, duplicates) - Throw exceptions only for truly unexpected/exceptional conditions (infrastructure failures)
- Leverage the implicit conversion:
return user;auto-wraps inResult<T>.Success(user)
Service Layer
- All service methods return
Result<T>orResult<object?>for void-like operations - Validate inputs at the top of each method; return
Failureimmediately on invalid input - Chain results: check
IsFailureon dependent calls before proceeding - Never catch exceptions to convert them to
Result— let infrastructure errors bubble
Extension Methods
- Map results to HTTP responses using
ToHttpResponse()orToHttpResponseWithNotFound() - Use
Results<Ok<T>, BadRequest<ErrorResponse>>for typed endpoint signatures - The "not found" variant inspects the error message for
"not found"(case-insensitive)
Naming & Style
- Follow PascalCase for public members, camelCase for privates
- Suffix async methods with
Async; always acceptCancellationTokenwhere applicable - Use
is null/is not null— never== null - Prefer file-scoped namespaces and records for DTOs
Error Messages
- Use descriptive, user-facing messages:
"User with ID {id} was not found" - Keep messages consistent across repository and service layers
- Never expose stack traces or internal details in error messages
Adding New Endpoints
- Define the model/DTO as a
recordinModels/ - Add repository method returning
Result<T>in the repository interface and implementation - Add service method with validation logic returning
Result<T> - Map the endpoint in
Program.csusingMapGet/MapPost/etc. with.ToHttpResponse()or.ToHttpResponseWithNotFound()
Anti-Patterns to Avoid
- Throwing exceptions for validation failures or not-found cases
- Using
.Valuewithout checkingIsSuccessfirst - Returning
nullinstead ofResult<T>.Failure(...) - Mixing Result pattern and exception-based error handling in the same flow