What is Middleware?
A component in ASP.NET Core that processes HTTP requests and responses in a pipeline.
Runs in sequence → Can handle/modify request → Call next → Return response
Middleware Pipeline Flow
Request → [Exception Handler]
→ [Routing]
→ [Authentication]
→ [Authorization]
→ [Custom Middleware]
→ [Endpoints]
Response ←──────────────────────────
Registering Middleware
app.UseMiddleware<CustomMiddleware>();
app.Use(async (context, next) =>
{
// before next middleware
await next();
// after next middleware
});
Built-In Middleware (Order Matters)
| Category | Examples |
|---|
| Error Handling | UseExceptionHandler(), UseDeveloperExceptionPage() |
| Routing | UseRouting() |
| Security | UseAuthentication(), UseAuthorization(), UseCors() |
| Performance | UseResponseCompression() |
| Session | UseSession() |
| Static Files | UseStaticFiles() |
| Endpoint Mapping | UseEndpoints() |
Middleware Rules
1. Must call await next() to continue
2. Order is very important
3. Do not run time-heavy logic
4. Avoid database calls unless required
Custom Middleware Example
public class RequestLogMiddleware
{
private readonly RequestDelegate _next;
public RequestLogMiddleware(RequestDelegate next) => _next = next;
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Request: " + context.Request.Path);
await _next(context);
}
}
Register
app.UseMiddleware<RequestLogMiddleware>();
Dependency Injection (DI) Cheat Sheet
What is DI?
Design pattern where dependencies are injected instead of being hard-coded.
.NET Core has a built-in DI container
DI Service Lifetimes
| Lifetime | Scope | Best For |
|---|
| Singleton | App lifetime | Config, Cache, Logging |
| Scoped | Per request | DbContext, business services |
| Transient | New instance | Lightweight services, helpers |
Registering Services
builder.Services.AddSingleton<ILogger, Logger>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddTransient<INotifier, NotificationService>();
DI Best Practices
| Good | Avoid |
|---|
| Inject interfaces | Inject concrete classes |
| Use IOptions<> for config | Inject IConfiguration everywhere |
| Dispose unmanaged resources | Singleton using scoped DB context |
| Use factory pattern when needed | Constructor with 10+ parameters |
Common DI Mistake
Singleton depends on scoped
// WRONG: scoped inside singleton leads to memory leaks
builder.Services.AddSingleton<ServiceA>();
builder.Services.AddScoped<ServiceB>(); // ServiceA depends on this
Inject in Controller
public class UserController : ControllerBase
{
private readonly IUserService _svc;
public UserController(IUserService svc) => _svc = svc;
[HttpGet]
public string GetUser() => _svc.GetUser();
}
Trick Interview Answers (Short & Strong)
| Question | Best Answer |
|---|
| Why Middleware? | Central processing pipeline for requests |
| Order Importance? | Security & routing break if wrong order |
| Why DI? | Loose coupling, testability, maintenance |
| Difference between AddScoped vs AddSingleton | Scoped per request, Singleton per app |
| Memory leak cause in DI? | Singleton holding scoped instance |
Quick Diagrams
Middleware Flow
app.Use1 → app.Use2 → app.Use3 → Endpoint
↑ ↑ ↑ ↑
Response ←───┘─────────┘─────────┘
DI Lifetime Visual
Singleton: One instance forever
Scoped: One instance per request
Transient: Fresh instance everytime
Bonus Mnemonics
| Concept | Trick |
|---|
| Middleware Order | Ex-Route-Auth-End (Exception → Routing → Auth → Endpoints) |
| DI Lifetimes | SST (Singleton-Scoped-Transient) = Stable-Session-Short |
Conclusion
Mastering Middleware + DI = clean, scalable, high-performance ASP.NET Core apps.