public class GetProductQuery : IRequest { public int Id { get; set; } }
public class GetProductHandler : IRequestHandler
{
public async Task Handle(GetProductQuery request, CancellationToken cancellationToken)
{
return new ProductDto { Id = request.Id, Name = "Test" };
}
}
// Controller
public class ProductsController : ControllerBase
{
private readonly IMediator _mediator;
public ProductsController(IMediator mediator) => _mediator = mediator;
[HttpGet("{id}")]
public async Task Get(int id) => Ok(await _mediator.Send(new GetProductQuery { Id = id }));
}
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext();
builder.Services.AddScoped();
var app = builder.Build();
app.UseRouting();
app.MapControllers();
app.Run();
}
}
public class MyService
{
private readonly IMemoryCache _cache;
private readonly ILogger _logger;
public MyService(IMemoryCache cache, ILogger logger)
{
_cache = cache;
_logger = logger;
}
public string GetData(string key)
{
if (!_cache.TryGetValue(key, out string value))
{
_logger.LogInformation("Cache miss for {Key}", key);
value = "Data";
_cache.Set(key, value, TimeSpan.FromMinutes(10));
}
return value;
}
}
public interface IRepository { Task> GetAllAsync(); }
public class Repository : IRepository where T : class
{
private readonly MyDbContext _context;
public Repository(MyDbContext context) => _context = context;
public async Task> GetAllAsync() => await _context.Set().ToListAsync();
}
public interface IUnitOfWork
{
IRepository Products { get; }
Task SaveChangesAsync();
}
public class UnitOfWork : IUnitOfWork
{
private readonly MyDbContext _context;
public IRepository Products { get; }
public UnitOfWork(MyDbContext context)
{
_context = context;
Products = new Repository(context);
}
public async Task SaveChangesAsync() => await _context.SaveChangesAsync();
}
// Application Layer
public interface IProductService
{
Task> GetAllAsync();
}
// Infrastructure Layer
public class ProductRepository : IProductRepository
{
private readonly MyDbContext _context;
public ProductRepository(MyDbContext context) => _context = context;
public async Task> GetAllAsync() => await _context.Products.ToListAsync();
}
public class CreateProductCommand : IRequest { public string Name { get; set; } }
public class CreateProductHandler : IRequestHandler
{
private readonly MyDbContext _context;
public CreateProductHandler(MyDbContext context) => _context = context;
public async Task Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
var product = new Product { Name = request.Name };
_context.Products.Add(product);
await _context.SaveChangesAsync();
return product.Id;
}
}
public interface IPaymentStrategy
{
Task ProcessPayment(decimal amount);
}
public class PayPalStrategy : IPaymentStrategy
{
public async Task ProcessPayment(decimal amount) => await Task.CompletedTask; // PayPal logic
}
public class PaymentService
{
private readonly IPaymentStrategy _strategy;
public PaymentService(IPaymentStrategy strategy) => _strategy = strategy;
public async Task Process(decimal amount) => await _strategy.ProcessPayment(amount);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped();
}
public interface IServiceA { void DoWork(); }
public interface IServiceB { void DoWork(); }
public class ServiceA : IServiceA
{
private readonly IServiceB _serviceB;
public ServiceA(IServiceB serviceB) => _serviceB = serviceB;
public void DoWork() => _serviceB.DoWork();
}
public async Task> GetProductsAsync()
{
return await _context.Products
.AsNoTracking()
.Select(p => new ProductDto { Id = p.Id, Name = p.Name })
.ToListAsync();
}
public interface IProductRepository
{
Task GetByIdAsync(int id);
}
public class ProductRepository : IProductRepository
{
private readonly MyDbContext _context;
public ProductRepository(MyDbContext context) => _context = context;
public async Task GetByIdAsync(int id) => await _context.Products.FindAsync(id);
}
var products = await _context.Products.AsNoTracking().ToListAsync(); // Read-only
var product = await _context.Products.FirstOrDefaultAsync(p => p.Id == 1); // Update
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().Property("LastUpdated");
modelBuilder.Entity().Property("Status")
.HasConversion(v => v.ToString(), v => Enum.Parse(v));
}
var order = await _context.Orders
.Include(o => o.Customer)
.ThenInclude(c => c.Address)
.FirstOrDefaultAsync(o => o.Id == 1);
// Code-first
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
public class Product
{
public int Id { get; set; }
[ConcurrencyCheck]
public string Name { get; set; }
}
public async Task UpdateProductAsync(int id, string name)
{
var product = await _context.Products.FindAsync(id);
product.Name = name;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
// Handle conflict
}
}
public class Product
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().HasQueryFilter(p => !p.IsDeleted);
}
public class MyDbContext : DbContext
{
public override Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted))
{
entry.State = EntityState.Modified;
entry.Entity.GetType().GetProperty("IsDeleted")?.SetValue(entry.Entity, true);
}
return base.SaveChangesAsync(cancellationToken);
}
}
var products = await _context.Products
.Include(p => p.Category)
.ThenInclude(c => c.Supplier)
.Select(p => new { p.Id, p.Name })
.ToListAsync();
var products = await _context.Products
.FromSqlRaw("SELECT * FROM Products WHERE IsActive = 1")
.ToListAsync();
public class ProductController : ControllerBase
{
private readonly IProductService _service;
public ProductController(IProductService service) => _service = service;
[HttpGet]
public async Task Get() => Ok(await _service.GetAllAsync());
}
public class ProductService : IProductService
{
public async Task> GetAllAsync() => await Task.FromResult(new List());
}
public interface INotificationProvider
{
Task SendAsync(string message);
}
public class EmailProvider : INotificationProvider
{
public async Task SendAsync(string message) => await Task.CompletedTask;
}
public class NotificationService
{
private readonly INotificationProvider _provider;
public NotificationService(INotificationProvider provider) => _provider = provider;
public async Task NotifyAsync(string message) => await _provider.SendAsync(message);
}
public interface IRepository
{
Task SaveAsync();
}
public class ValidRepository : IRepository
{
public async Task SaveAsync() => await Task.CompletedTask;
}
// Violates LSP
public class InvalidRepository : IRepository
{
public Task SaveAsync() => throw new NotSupportedException();
}
public interface IMyService { string GetData(); }
public class MyService : IMyService { public string GetData() => "Data"; }
public class MyController : ControllerBase
{
private readonly IMyService _service;
public MyController(IMyService service) => _service = service;
[HttpGet]
public IActionResult Get() => Ok(_service.GetData());
}
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped();
}
public interface IReadRepository { Task> GetAllAsync(); }
public interface IWriteRepository { Task SaveAsync(Product product); }
public class ProductRepository : IReadRepository, IWriteRepository
{
public async Task> GetAllAsync() => await Task.FromResult(new List());
public async Task SaveAsync(Product product) => await Task.CompletedTask;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidIssuer = "MyIssuer",
ValidAudience = "MyAudience",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("my-secret-key"))
};
});
}
public class AuthController : ControllerBase
{
[HttpPost("refresh")]
public IActionResult Refresh(string refreshToken)
{
// Validate and issue new JWT
return Ok(new { token = "new-jwt", refreshToken = "new-refresh-token" });
}
}
public interface IMyService { string GetData(); }
public class MyService : IMyService { public string GetData() => "Data"; }
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped();
}
public class CorrelationIdMiddleware
{
private readonly RequestDelegate _next;
public CorrelationIdMiddleware(RequestDelegate next) => _next = next;
Underwood async Task InvokeAsync(HttpContext context, ILogger logger)
{
var correlationId = context.Request.Headers["CorrelationId"].FirstOrDefault() ?? Guid.NewGuid().ToString();
logger.LogInformation("Request with CorrelationId: {CorrelationId}", correlationId);
try
{
await _next(context);
}
catch (Exception ex)
{
logger.LogError(ex, "Error with CorrelationId: {CorrelationId}", correlationId);
context.Response.StatusCode = 500;
await context.Response.WriteAsync("Internal Server Error");
}
}
}
app.UseMiddleware();
public class MyController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Post() => Ok();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddStackExchangeRedisCache(options => options.Configuration = "localhost:6379");
}
public class MyService
{
private readonly IMemoryCache _cache;
public MyService(IMemoryCache cache) => _cache = cache;
public string GetData(string key)
{
if (!_cache.TryGetValue(key, out string value))
{
value = "Data";
_cache.Set(key, value, TimeSpan.FromMinutes(10));
}
return value;
}
}
public async Task> GetProductsAsync()
{
return await _context.Products
.AsNoTracking()
.Select(p => new Product { Id = p.Id, Name = p.Name })
.ToListAsync()
.ConfigureAwait(false);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/health");
}
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddDbContextCheck();
}
public void Configure(IApplicationBuilder app)
{
app.UseHealthChecks("/health");
}
public void ConfigureServices(IServiceCollection services)
{
services.AddFeatureManagement();
}
public class MyController : ControllerBase
{
private readonly IFeatureManager _featureManager;
public MyController(IFeatureManager featureManager) => _featureManager = featureManager;
[HttpGet]
public async Task Get()
{
if (await _featureManager.IsEnabledAsync("NewFeature"))
return Ok("New Feature Enabled");
return Ok("Old Feature");
}
}
public class ProductServiceTests
{
[Fact]
public async Task GetProducts_ReturnsProducts()
{
var options = new DbContextOptionsBuilder().UseInMemoryDatabase("TestDb").Options;
using var context = new MyDbContext(options);
context.Products.Add(new Product { Id = 1, Name = "Test" });
await context.SaveChangesAsync();
var service = new ProductService(context);
var products = await service.GetAllAsync();
Assert.Single(products);
}
}