.agents/skills/dotnet-best-practices/SKILL.md
Ensures .NET/C# code follows modern best practices, SOLID principles, and industry standards for production-ready applications
npx skillsauth add afonsoft/VideoChat dotnet-best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when you need to:
Input: C# code files or project structure
Output: Detailed analysis with recommendations
Please review this .NET code for best practices compliance:
1. Check SOLID principles adherence
2. Verify modern C# feature usage
3. Validate error handling patterns
4. Assess performance considerations
5. Review security practices
6. Evaluate testability
Input: Feature requirements and project context
Output: Complete implementation following best practices
Implement [feature name] following .NET best practices:
1. Use appropriate design patterns
2. Apply SOLID principles
3. Include proper error handling
4. Add comprehensive documentation
5. Consider performance implications
6. Ensure testability
Input: Existing code that needs improvement
Output: Refactored code with explanations
Refactor this code to follow .NET best practices:
1. Identify code smells and anti-patterns
2. Apply appropriate design patterns
3. Improve readability and maintainability
4. Optimize performance where applicable
5. Enhance error handling
6. Add missing documentation
Single Responsibility Principle (SRP)
Open/Closed Principle (OCP)
Liskov Substitution Principle (LSP)
Interface Segregation Principle (ISP)
Dependency Inversion Principle (DIP)
Null Safety
// Use nullable reference types
#nullable enable
// Null checks
ArgumentNullException.ThrowIfNull(value);
// Null-coalescing operators
string result = input ?? defaultValue;
string? nullableResult = input?.ToString();
Pattern Matching
// Switch expressions
string result = obj switch
{
string s => $"String: {s}",
int i => $"Integer: {i}",
null => "Null",
_ => "Unknown"
};
// Property patterns
if (person is { Age: >= 18 })
{
// Adult logic
}
Records and Init-Only Properties
// Immutable records
public record Person(string Name, int Age);
// Init-only properties
public class Product
{
public string Name { get; init; }
public decimal Price { get; init; }
}
Async/Await Best Practices
// ConfigureAwait for library code
var result = await SomeAsyncMethod().ConfigureAwait(false);
// Async all the way down
public async Task<string> GetDataAsync()
{
var data = await _service.GetDataAsync();
return ProcessData(data);
}
// Classes: PascalCase
public class CustomerService { }
// Methods: PascalCase
public async Task<Customer> GetCustomerAsync(int id) { }
// Properties: PascalCase
public string CustomerName { get; set; }
// Fields: camelCase (private), _camelCase (private readonly)
private readonly ILogger<CustomerService> _logger;
private string _customerName;
// Constants: PascalCase
public const int MaxRetries = 3;
// Interfaces: PascalCase with I prefix
public interface IRepository<T> { }
// Enums: PascalCase
public enum OrderStatus { Pending, Processing, Shipped }
// Specific exceptions
throw new InvalidOperationException("Invalid operation state");
// Guard clauses
public void ProcessOrder(Order order)
{
ArgumentNullException.ThrowIfNull(order);
if (order.Items.Count == 0)
throw new ArgumentException("Order cannot be empty");
// Process order
}
// Try-catch with specific exceptions
try
{
await _orderProcessor.ProcessAsync(order);
}
catch (OrderValidationException ex)
{
_logger.LogError(ex, "Order validation failed");
throw;
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error processing order");
throw new OrderProcessingException("Failed to process order", ex);
}
// Constructor injection
public class OrderService
{
private readonly IOrderRepository _repository;
private readonly ILogger<OrderService> _logger;
public OrderService(IOrderRepository repository, ILogger<OrderService> logger)
{
_repository = repository;
_logger = logger;
}
}
// Service registration
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddOrderServices(this IServiceCollection services)
{
services.AddScoped<IOrderRepository, OrderRepository>();
services.AddScoped<IOrderService, OrderService>();
return services;
}
}
// Use AsNoTracking for read-only queries
var customers = await _context.Customers
.AsNoTracking()
.Where(c => c.IsActive)
.ToListAsync();
// Project only needed columns
var customerDtos = await _context.Customers
.Where(c => c.IsActive)
.Select(c => new CustomerDto
{
Id = c.Id,
Name = c.Name,
Email = c.Email
})
.ToListAsync();
// Use proper indexing
public class Customer
{
[Key]
public int Id { get; set; }
[Indexed]
public string Email { get; set; }
public string Name { get; set; }
}
// Use using statements for IDisposable
using var scope = _serviceProvider.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<IMyService>();
// Avoid memory leaks
public class ImageProcessor : IDisposable
{
private readonly MemoryStream _stream;
public ImageProcessor()
{
_stream = new MemoryStream();
}
public void Dispose()
{
_stream?.Dispose();
}
}
// Validate input parameters
public class CreateOrderRequest
{
[Required]
[StringLength(100, MinimumLength = 3)]
public string CustomerName { get; set; }
[Range(0.01, 10000.00)]
public decimal Amount { get; set; }
[EmailAddress]
public string Email { get; set; }
}
// Use claims-based authorization
[Authorize]
[ApiController]
public class OrdersController : ControllerBase
{
[HttpGet("{id}")]
[Authorize(Policy = "CanReadOrders")]
public async Task<ActionResult<Order>> GetOrder(int id)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var order = await _orderService.GetOrderAsync(id, userId);
if (order == null)
return NotFound();
return Ok(order);
}
}
public class OrderServiceTests
{
private readonly Mock<IOrderRepository> _repositoryMock;
private readonly Mock<ILogger<OrderService>> _loggerMock;
private readonly OrderService _service;
public OrderServiceTests()
{
_repositoryMock = new Mock<IOrderRepository>();
_loggerMock = new Mock<ILogger<OrderService>>();
_service = new OrderService(_repositoryMock.Object, _loggerMock.Object);
}
[Fact]
public async Task CreateOrder_ValidOrder_ReturnsOrderId()
{
// Arrange
var request = new CreateOrderRequest
{
CustomerName = "John Doe",
Amount = 100.00m
};
var expectedOrder = new Order { Id = 1, CustomerName = request.CustomerName };
_repositoryMock.Setup(r => r.AddAsync(It.IsAny<Order>()))
.ReturnsAsync(expectedOrder);
// Act
var result = await _service.CreateOrderAsync(request);
// Assert
result.Should().Be(1);
_repositoryMock.Verify(r => r.AddAsync(It.IsAny<Order>()), Times.Once);
}
}
Null Reference Exceptions
Performance Issues
Memory Leaks
Dependency Injection Issues
public class OrderService : IOrderService
{
private readonly IOrderRepository _repository;
private readonly ILogger<OrderService> _logger;
private readonly IOrderValidator _validator;
public OrderService(
IOrderRepository repository,
ILogger<OrderService> logger,
IOrderValidator validator)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_validator = validator ?? throw new ArgumentNullException(nameof(validator));
}
public async Task<int> CreateOrderAsync(CreateOrderRequest request)
{
ArgumentNullException.ThrowIfNull(request);
// Validate request
var validationResult = await _validator.ValidateAsync(request);
if (!validationResult.IsValid)
{
throw new ValidationException(validationResult.Errors);
}
// Create order
var order = new Order
{
CustomerName = request.CustomerName,
Amount = request.Amount,
CreatedAt = DateTime.UtcNow,
Status = OrderStatus.Pending
};
try
{
var orderId = await _repository.AddAsync(order);
_logger.LogInformation("Order {OrderId} created successfully", orderId);
return orderId;
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to create order");
throw new OrderCreationException("Failed to create order", ex);
}
}
public async Task<Order?> GetOrderAsync(int id, string userId)
{
if (id <= 0)
throw new ArgumentException("Invalid order ID", nameof(id));
if (string.IsNullOrWhiteSpace(userId))
throw new ArgumentException("User ID is required", nameof(userId));
var order = await _repository.GetByIdAsync(id);
if (order == null || order.UserId != userId)
return null;
return order;
}
}
This skill provides comprehensive guidance for .NET development best practices. Use it to ensure your code meets industry standards and follows modern patterns.
development
This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like "review website design", "check the UI", "fix the layout", "find design problems". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level.
testing
Comprehensive unit testing with xUnit, mocking, test patterns, and best practices for .NET applications
data-ai
Universal SQL performance optimization assistant for comprehensive query tuning, indexing strategies, and database performance analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Provides execution plan analysis, pagination optimization, batch operations, and performance monitoring guidance.
development
Universal SQL code review assistant that performs comprehensive security, maintainability, and code quality analysis across all SQL databases (MySQL, PostgreSQL, SQL Server, Oracle). Focuses on SQL injection prevention, access control, code standards, and anti-pattern detection. Complements SQL optimization prompt for complete development coverage.