Key .NET Concepts vs. Spring (The “Next Level”)
1. Middleware Pipeline vs. Spring Security Filter Chain
-
Spring: Uses a heavy servlet-based filter chain and Spring Security configurations where you override
WebSecurityConfigurerAdapter(or modern component-based security chains). -
.NET: Uses a linear Middleware Pipeline built directly into HTTP request handling via
app.Use(...)extensions. Every piece of request processing—authentication, static files, routing, exception handling—is explicitly stacked as a onion-like layer inProgram.cs.
2. Entity Framework (EF Core) vs. Hibernate / JPA
-
Spring/JPA: Relies heavily on annotations (
@Entity,@Table,@ManyToOne) and proxy objects to handle state, dirty tracking, and lazy loading under Hibernate. -
.NET (EF Core): Uses code-first mapping via a
DbContextand LINQ (Language Integrated Query). Unlike Java streams, LINQ translates directly into expression trees that execute heavily optimized SQL natively at the database level.
3. Async/Await Model
-
Spring: Traditionally built on blocking I/O (though Spring WebFlux brought reactive programming via Project Reactor).
-
.NET: Built from the ground up to be Asynchronous by default. The
async/awaitpattern propagates from the controller all the way down to the database driver (async/awaittasks), resulting in massive throughput with minimal thread pool starvation.
High-Yield .NET Interview Questions (With Spring Contrasts)
Q1: What is a “Captive Dependency” in .NET, and how does the container prevent it?
-
The Trap: Trying to answer with a generic definition of dependency injection.
-
The Answer: A captive dependency happens when a longer-lived service (like a
Singleton) holds a reference to a shorter-lived service (like aScopeddatabase context). In .NET, if a singleton captures a scoped service, that scoped service is inadvertently trapped in memory forever, bypassing its per-request lifecycle and causing massive concurrency bugs. -
How .NET handles it: ASP.NET Core has a built-in scope validation mechanism. In development mode, the DI container throws an explicit exception on startup if it detects a singleton depending on a scoped service. (Spring behaves more implicitly here, which often hides the bug until production).
Q2: How does middleware execution order affect your application?
-
The Trap: Thinking order doesn’t matter as long as services are registered.
-
The Answer: In .NET, because the HTTP pipeline is processed sequentially via delegates (
RequestDelegate), order is everything. For example, if you placeapp.UseAuthorization()beforeapp.UseAuthentication(), your authorization middleware will run before the user’s identity has even been established, breaking your security flow.
Q3: What is the difference between AddTransient, AddScoped, and AddSingleton, and how do they map to Spring scopes?
- Transient: A new instance is created every single time it is requested anywhere. (Similar to Spring’s
prototype). - Scoped: One instance is created per HTTP request. (Closest to Spring’s HTTP request-bound scopes).
- Singleton: One instance is created the very first time and shared across the entire application lifecycle. (Identical to Spring’s default
singleton).
Q4: Why does .NET discourage Field Injection (@Autowired equivalents), unlike Spring?
- The Answer: .NET heavily enforces Constructor Injection to ensure compile-time safety and immutability. If a class requires dependencies to function, making them
private readonlyfields set via the constructor guarantees the object can never exist in an invalid, half-initialized state. Field injection relies on post-construction reflection manipulation, which hides dependencies and makes unit testing much harder without container bootstrapping.
—