Skip to main content

Command Palette

Search for a command to run...

ASP.NET Core Middleware Interview Questions for Senior .NET Developers (2026)

Updated
β€’9 min read
ASP.NET Core Middleware Interview Questions for Senior .NET Developers (2026)

ASP.NET Core middleware is one of the most consistently tested topics in senior .NET developer interviews β€” and one of the most commonly misunderstood. Interviewers use it to probe whether a candidate understands the request pipeline, knows how to write production-safe custom middleware, and can reason about ordering, short-circuiting, and cross-cutting concerns with precision.

This guide covers the middleware questions most likely to appear in a senior .NET interview in 2026, with direct answers that reflect how experienced developers actually think about the topic.

🎁 Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. πŸ‘‰ Join us on Patreon

Basic Questions

What is middleware in ASP.NET Core?

Middleware is a component assembled into the application pipeline to handle HTTP requests and responses. Each middleware component can perform work before and after the next component in the pipeline, and can choose to pass the request to the next component or short-circuit the pipeline entirely. Middleware components are executed in the order they are added in Program.cs.

What is the difference between Use, Run, and Map in ASP.NET Core middleware?

Use adds middleware that can call the next delegate in the pipeline. It receives both the HttpContext and the RequestDelegate for the next middleware, giving it the option to call or skip the next component. Run adds terminal middleware that does not call the next delegate β€” the pipeline ends there. Map branches the pipeline based on a URL path prefix; requests matching the path are handled by the branched pipeline, while others continue through the main pipeline.

Why does middleware order matter?

The request pipeline is a chain where each component processes the request in registration order and the response in reverse order. Order determines which middleware can observe or modify a request before it reaches an endpoint, and which middleware can observe or modify a response before it is sent to the client. Placing authentication middleware after routing but before authorization, for example, is not a stylistic choice β€” it is a correctness requirement.

What is the difference between IMiddleware and the convention-based middleware approach?

Convention-based middleware uses a class with an InvokeAsync(HttpContext, RequestDelegate) method and a constructor that accepts the RequestDelegate. It is instantiated once at startup by the DI container and reused for every request. IMiddleware, introduced in ASP.NET Core 2.0, defines an interface with InvokeAsync(HttpContext, MiddlewareDelegate). Classes implementing IMiddleware are resolved from the DI container per-request, meaning they can have scoped dependencies injected directly into the constructor rather than into InvokeAsync. If your middleware needs scoped services, IMiddleware is the cleaner approach.


Intermediate Questions

How do you write middleware that only runs for specific routes?

The cleanest approach is UseWhen or MapWhen, which branch the pipeline conditionally based on a predicate evaluated against the HttpContext. UseWhen rejoins the main pipeline after the branch executes; MapWhen does not. For route-specific behaviour in a more structured way, endpoint filters (available in Minimal APIs) or action filters (in controllers) are often more appropriate than branching the middleware pipeline.

What is the risk of using HttpContext outside of the request thread in middleware?

HttpContext is not thread-safe and is tied to the lifetime of a single request. Capturing it in a closure, storing it in a static variable, or accessing it from a background thread after the request completes leads to undefined behaviour, disposed object exceptions, or silent data corruption. The correct approach for passing HttpContext data to background work is to extract the needed values (such as a correlation ID or user claim) before the request ends and pass those values to the background task, not the context itself.

How does short-circuiting work, and when should you use it?

A middleware component short-circuits the pipeline by writing directly to HttpContext.Response and returning without calling next(context). This is appropriate when the middleware can definitively reject or fulfil the request without any downstream processing β€” for example, returning 401 Unauthorized when an authentication token is missing or invalid, or returning a cached response without hitting the endpoint. Short-circuiting incorrectly (for example, skipping authentication middleware by returning early) is a common security mistake.

Can middleware have scoped dependencies? How?

Middleware registered with app.UseMiddleware<T>() is a singleton β€” it is instantiated once. Injecting scoped services into its constructor causes a captive dependency bug: the scoped service is resolved once at startup and shared across all requests, violating its intended lifetime. The correct approach is to either inject the scoped service into InvokeAsync directly (ASP.NET Core supports parameter injection there), use IMiddleware which resolves per-request, or resolve the service manually from HttpContext.RequestServices inside InvokeAsync.

What is the difference between middleware and endpoint filters in ASP.NET Core?

Middleware operates at the pipeline level and runs for every request, regardless of whether an endpoint is matched. Endpoint filters operate at the endpoint level and run only after routing has matched a specific endpoint. Endpoint filters have access to endpoint metadata and the result of the handler, making them suitable for validation, transformation, and short-circuiting at the operation level. Middleware is better for cross-cutting concerns that apply across all requests: logging, authentication, CORS, rate limiting, and exception handling.


Advanced Questions

How would you implement correlation ID middleware correctly in production?

A production-correct correlation ID middleware should: check for an incoming X-Correlation-ID header and reuse it if present (preserving the caller's ID for distributed tracing); generate a new Guid if none is present; store the ID in HttpContext.Items for downstream access; use Response.OnStarting to add the header to the response (not setting it directly, which can fail after headers are sent); and integrate with the logging scope so every log line within the request carries the correlation ID via ILogger.BeginScope. Logging the ID only at the start and end of the request is insufficient for debugging distributed failures.

What happens if an exception is thrown inside middleware and UseExceptionHandler is not registered?

The exception propagates up the middleware stack, potentially exposing a 500 response with stack trace details depending on the environment. In Development, ASP.NET Core's developer exception page middleware shows the full exception. In Production without exception handling middleware, Kestrel typically returns a 500 with minimal detail, but the response is not guaranteed to follow any structured format. The correct approach is to register app.UseExceptionHandler() early in the pipeline (before any middleware that might throw), backed by IExceptionHandler implementations that map exceptions to RFC 7807 Problem Details responses.

How would you test custom middleware?

The recommended approach is integration testing using WebApplicationFactory<T> from Microsoft.AspNetCore.Mvc.Testing. This spins up a real in-memory test server with the full middleware pipeline, allowing you to send HttpClient requests and assert on the response status, headers, and body. Unit testing middleware in isolation requires creating a DefaultHttpContext, constructing the middleware manually, and calling InvokeAsync directly β€” this is useful for testing the middleware logic but does not cover pipeline ordering or interaction with other middleware.

What is the RequestDelegate and how is it composed?

RequestDelegate is a delegate with the signature Task(HttpContext). It represents the next action in the middleware pipeline. When you call app.Use(...), ASP.NET Core builds a chain of RequestDelegate instances at startup β€” each middleware wraps the next into a closure, forming a pipeline. This composition happens once, and the resulting root RequestDelegate is stored and invoked for every incoming request. Understanding this helps explain why middleware is performant (no reflection per request) and why order of registration is immutable after the app is built.

How does UseRouting interact with middleware ordering?

UseRouting adds the endpoint routing middleware, which matches an incoming request to a registered endpoint and stores the match in HttpContext. Middleware registered before UseRouting cannot access the matched endpoint because it has not been resolved yet. Middleware registered between UseRouting and UseEndpoints (or MapControllers, MapGet, etc.) can access the matched endpoint via context.GetEndpoint() β€” this is where authorization middleware correctly sits, because it needs to read endpoint metadata (such as [Authorize] attributes) to make its decision. Placing authorization before routing is a correctness bug: the endpoint has not been resolved, so metadata-based authorization decisions cannot be made.


Scenario-Based Questions

An API is returning 200 for all requests including failed ones. What middleware issue might cause this?

A middleware component is likely short-circuiting the pipeline and writing a 200 response before the request reaches the actual endpoint or exception handler. Common causes include incorrectly implemented response caching middleware that returns a cached 200 for a route that has since started failing, or custom middleware that catches exceptions and swallows them by writing a 200 without re-throwing. The fix is to ensure exception-handling middleware is registered first, custom middleware does not swallow exceptions silently, and any middleware that writes to the response always sets the correct status code.

How would you implement a request timeout mechanism using middleware?

ASP.NET Core 8 introduced AddRequestTimeouts and UseRequestTimeouts as first-party middleware for this. For earlier versions, the pattern is to create a CancellationTokenSource with a timeout in InvokeAsync, link it to HttpContext.RequestAborted, and pass the combined token to downstream handlers. The middleware must handle OperationCanceledException and write a 504 Gateway Timeout response when the token fires. The key requirement is that all downstream async operations must accept and respect the CancellationToken β€” middleware-level timeouts are ineffective if handlers ignore cancellation.

πŸ’» See real middleware patterns running in production-ready code β€” check out our open-source Request Correlation Middleware sample and Request Timeout Middleware sample on GitHub.


Quick-Reference Summary

Topic Key Point to Communicate
Middleware order Authentication before authorization; exception handler first
Use vs Run vs Map Use passes control; Run terminates; Map branches
Scoped dependencies Inject into InvokeAsync, use IMiddleware, or resolve from RequestServices
HttpContext thread safety Never capture or access outside the request thread
Short-circuiting Valid for rejection; never bypass security middleware
Testing WebApplicationFactory for integration; DefaultHttpContext for unit
Endpoint filters vs middleware Filters run post-routing; middleware runs for all requests
RequestDelegate Precompiled chain at startup; no per-request reflection

β˜• Found this article helpful? Buy us a coffee β€” it helps us keep producing free, high-quality .NET content every week.

More from this blog

C

Coding Droplets

127 posts