Vivek Kaushik
AboutBlogWorkMy Work Ethics

🌐 ASP.NET Core / .NET Backend Notes


1️⃣ Request Pipeline Architecture

High-Level Flow

Kestrel (Web Server) ↓ Middleware Pipeline (in order of registration) ↓ Routing ↓ Endpoint Execution (Controller / Minimal API) ↓ Response flows back up the pipeline
Important:
  • Middleware executes in order registered
  • Response flows in reverse order
  • Order matters critically

Middleware Execution Model

If registered like:
app.Use(A); app.Use(B); app.Use(C); app.Run(D);
Execution order:
A → B → C → D C → B → A
Think nested wrappers.

2️⃣ Middleware vs Filters

Middleware

  • HTTP-level
  • Runs before MVC
  • Applies globally
  • Framework-agnostic
  • Can short-circuit early
Use for:
  • Authentication
  • Authorization
  • CORS
  • Global exception handling
  • Correlation IDs
  • Logging

Filters (MVC only)

Run inside MVC pipeline.
Types:
  • Authorization filters
  • Resource filters
  • Action filters
  • Exception filters
  • Result filters
Use when:
  • Need access to action arguments
  • Need ModelState
  • Need controller context

Key Distinction

Middleware = HTTP layer
Filters = MVC layer
Global exception handling → Prefer middleware

3️⃣ Use vs Run vs Map

app.Use()

  • Adds middleware
  • Must call await next()
  • Can execute before and after next

app.Run()

  • Terminal middleware
  • Ends pipeline
  • No next()

app.Map()

  • Branches pipeline based on path
  • Creates sub-pipeline

4️⃣ Dependency Injection (DI)

Lifetimes

Singleton

  • One instance for app lifetime
  • Created once at startup

Scoped

  • One instance per request

Transient

  • New instance every resolution

Dangerous Injection Rule

Singleton ❌ cannot depend on Scoped
Why?
  • Scoped tied to request lifetime
  • Singleton lives entire app lifetime
  • Causes disposed object or lifetime leak

Correct Fix Pattern

Use IServiceScopeFactory inside singleton:
using var scope = _scopeFactory.CreateScope(); var service = scope.ServiceProvider.GetRequiredService<MyScopedService>();

5️⃣ Model Binding & Validation

Model Binding

  • JSON → C# object
  • Uses input formatter (System.Text.Json)
  • Adds errors to ModelState

Validation

  • Runs after successful binding
  • Uses DataAnnotations
  • Adds errors to ModelState

Automatic 400 Behavior

If [ApiController] present:
  • Invalid ModelState → automatic 400
  • Controller method not executed
Without [ApiController]:
  • Must manually check ModelState

6️⃣ Customizing 400 Responses

Use:
builder.Services.Configure<ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = context => { return new BadRequestObjectResult(...); }; });
Modern (.NET 8+):
builder.Services.AddProblemDetails();
Customize via:
options.CustomizeProblemDetails

7️⃣ Global Exception Handling

Preferred Approach

Middleware-based:
app.UseExceptionHandler();
Why?
  • Catches everything
  • Even before MVC executes
  • Centralized logging
  • Prevents stack trace leaks

Order Matters

Register early:
app.UseExceptionHandler(); app.UseAuthentication(); app.UseAuthorization();

8️⃣ Background Services

IHostedService

Manual lifecycle management.

BackgroundService

Preferred base class.
Override:
ExecuteAsync()
Handles cancellation wiring.

Distributed Scale Problem

Hosted services run per instance.
Scaling → multiple executions.
Solutions:
  • Separate worker service
  • Distributed lock (Redis / Blob lease)
  • Hangfire (persistent scheduler)
  • Azure Functions (Timer trigger)

9️⃣ HttpClient & IHttpClientFactory

Why Not Plain HttpClient?

  • Socket exhaustion
  • DNS refresh issues
  • Connection pooling mismanagement

IHttpClientFactory Benefits

  • Centralized configuration
  • Connection pooling
  • DNS refresh
  • Resilience policies
  • Typed clients

Typed Client Example

services.AddHttpClient<MyApiClient>();
Cleaner, testable, DI-friendly.

🔟 Logging

Log Levels

  • Trace
  • Debug
  • Information
  • Warning
  • Error
  • Critical
  • None

Structured Logging

Good:
_logger.LogInformation("User {UserId} created order {OrderId}", userId, orderId);
Bad:
_logger.LogInformation($"User {userId} created order {orderId}");
Structured logs enable queryable properties.

1️⃣1️⃣ Observability

Logs

Discrete events.
Answer: What happened?

Metrics

Numerical aggregates.
Answer: How is system performing?
Examples:
  • RPS
  • CPU
  • Latency

Traces

Distributed request flow.
Answer: Where did time go?
Tracks:
  • Spans
  • Dependencies
  • Timing
  • Correlation

1️⃣2️⃣ Correlation IDs

Pattern:
  • Middleware generates or reads header
  • Stored in logging scope
  • Propagated via HTTP headers
Modern systems:
  • Use Activity / OpenTelemetry
  • Integrated with App Insights

1️⃣3️⃣ Thread Pool in ASP.NET Core

  • No SynchronizationContext
  • Runs on ThreadPool
  • Async releases threads during I/O
  • Blocking causes starvation

1️⃣4️⃣ Thread Pool Starvation

Caused by:
  • .Result
  • .Wait()
  • Blocking I/O
  • Overuse of Task.Run
Effect:
  • Requests queue up
  • Throughput collapse

1️⃣5️⃣ When NOT to Use Task.Run

Do NOT use for:
  • Database calls
  • HTTP calls
  • I/O operations
ASP.NET Core already uses ThreadPool.

🎯 Final Interview Summary (Backend)

Strong ASP.NET Core candidate should understand:
  • Request pipeline architecture
  • DI lifetimes & scope safety
  • Async scalability
  • Middleware vs Filters
  • Model binding internals
  • Exception handling strategy
  • Observability stack
  • Background job scaling concerns
  • HttpClient best practices
  • Thread pool behavior

 
Copyright 2026 Vivek Kaushik