Previously, in Part 4, you sharpened your C# with collections and LINQ. Now we climb one layer up the stack, to where most .NET interviews spend most of their time: ASP.NET Core and Web APIs. These four questions show up in almost every loop, and each one has a version of the answer that makes an interviewer sit up straight.
"Walk me through the middleware pipeline."
Why they ask it: Anyone can scaffold a Web API. This question checks whether you know what actually happens between the request arriving and your controller running. If you understand the pipeline, you can debug the weird stuff: mysterious 401s, CORS errors, exception handlers that never fire.
A strong answer: The pipeline is an ordered chain of components. A request enters at the top, passes through each middleware on the way in, hits a terminal endpoint, and then the response travels back out through the same chain in reverse — like layers of an onion. Each middleware can do work before calling the next one, do work after it returns, or short-circuit entirely and never call the rest. That short-circuiting is exactly how authentication returns a 401 without ever reaching your endpoint.
var app = builder.Build();
// Runs on the way IN and again on the way OUT
app.Use(async (context, next) =>
{
Console.WriteLine($"In: {context.Request.Path}");
await next();
Console.WriteLine($"Out: {context.Response.StatusCode}");
});
// Terminal middleware — nothing registered after this will run
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from the end of the pipeline!");
});
Then land the key point: order matters. Authentication must run before authorization (you have to know who someone is before checking what they may do), and both must run before your endpoints. Exception-handling middleware goes first, so it wraps everything below it.
Try it: Create a minimal API, add two app.Use middlewares that each log
a line before and after await next(), and watch the console. The nesting order you see is
the onion in action — you will never forget it after seeing it once.
Follow-ups to expect:
- "What happens if a middleware never calls
next()?" — It short-circuits; everything below it is skipped. - "Why must
UseAuthenticationcome beforeUseAuthorization?" — Identity must be established before policies can be checked. - "Where do you put exception-handling middleware, and why?" — First in the chain, so it catches exceptions from everything after it.
Red flag: Reciting a memorized list of middleware names in order without being able to say why the order matters. If you can explain one concrete failure caused by wrong ordering, you are ahead of most candidates.
"Explain DI lifetimes: singleton, scoped, transient."
Why they ask it: This is the classic ASP.NET Core question, because getting a
lifetime wrong produces bugs that only appear under load — shared state leaking between users, or a
DbContext being hammered by multiple threads. Interviewers want to know you won't plant
that landmine.
A strong answer: Keep it in plain words first, then add the trap.
| Lifetime | In plain words | Typical use |
|---|---|---|
| Singleton | One instance for the whole application, forever | Caches, configuration readers |
| Scoped | One instance per HTTP request | DbContext, unit-of-work services |
| Transient | A brand-new instance every single time it is requested | Lightweight, stateless helpers |
Then mention that EF Core's DbContext is registered as scoped for a reason: it is not
thread-safe, and one-per-request keeps each request's changes isolated.
Try it: Write a tiny service whose constructor sets a Guid property.
Register it three times under three interfaces — one per lifetime — inject all three into an endpoint
twice, and compare the Guids across two requests. Ten minutes, and lifetimes click permanently.
Follow-ups to expect:
- "What lifetime is
DbContextand why?" — Scoped; it is stateful and not thread-safe. - "What happens if a singleton depends on a scoped service?" — See the red flag below; in development, scope validation throws to save you.
- "When is transient the wrong choice?" — When the service is expensive to construct or holds resources you want reused.
Red flag: Not knowing the captive dependency trap. If a singleton
takes a scoped service in its constructor, that "scoped" instance is captured and lives as long as the
singleton — one DbContext quietly shared by every request in the app. Name this trap
unprompted and you sound like someone who has debugged it at 2 a.m.
"How would you design a clean REST API for appointments?"
Why they ask it: This tests taste, not trivia. Interviewers have inherited APIs full of
/getAppointments and /doCancel endpoints, and they are checking whether you will
add to that pile. (If REST is still fuzzy, our
pizza shop explainer builds it from scratch.)
A strong answer: URLs are nouns, HTTP methods are the verbs, and status codes tell the story. For a clinic's appointments:
| Method and URL | Meaning | Typical responses |
|---|---|---|
| GET /api/v1/appointments | List (with paging query params) | 200 |
| GET /api/v1/appointments/42 | Fetch one | 200, 404 |
| POST /api/v1/appointments | Book a new appointment | 201 + Location header, 400, 409 |
| PUT /api/v1/appointments/42 | Update it | 204, 404 |
| DELETE /api/v1/appointments/42 | Remove it | 204, 404 |
The 409 Conflict on POST is the detail that impresses: if the slot was just taken, say so with the right
code instead of a vague 400. For versioning, one sentence is enough: "I'd put v1 in the URL
because it's the most discoverable option, and plan versions from day one because retrofitting them hurts."
Try it: Sketch the endpoint for canceling an appointment. Is it a DELETE, or is a cancellation really a status change you might report on later? Write down your reasoning — this exact debate comes up in interviews, and either answer works if you can defend it.
Follow-ups to expect:
- "Cancel: DELETE or state change?" — Usually a state change (PATCH or a POST to
/cancel) because the business cares about canceled appointments. - "What do you return when the slot is already booked?" — 409 Conflict with a helpful body.
- "How do you page the list endpoint?" — Query parameters with sensible defaults and a maximum page size.
Red flag: Verbs in every URL and 200 for every outcome, including errors with a
"success": false body. That tells the interviewer you have used APIs but never had to
live with one.
"How does JWT authentication actually work?"
Why they ask it: Almost every modern .NET API uses token auth, and almost every candidate says "the token proves who you are" and stops. The question separates people who have configured JWT from people who understand it.
A strong answer: A JWT is three Base64Url-encoded parts joined by dots:
header.payload.signature. The header names the signing algorithm, the payload carries claims
(user id, roles, expiry), and the signature is computed by the server over the first two parts using a
secret key. When a request arrives, the server recomputes the signature and compares — if anything in the
payload was tampered with, the signatures won't match. Crucially, the payload is encoded, not
encrypted: anyone can read it, they just can't forge it. Because the token itself carries the proof,
the server stores no session — that's what makes JWT auth stateless and easy to scale.
Since tokens can't easily be revoked, keep them short-lived and use a refresh token to mint new ones.
Finish with storage, because it's the follow-up anyway: in the browser, avoid localStorage —
any XSS payload can read it. Prefer an httpOnly, secure cookie, which script cannot touch.
Try it: Generate a token in a sample app and decode its first two parts (any Base64Url decoder works). Seeing your own claims sitting there in plain text is the fastest cure for "I'll just put the user's data in the token."
Follow-ups to expect:
- "How do you log someone out if the server is stateless?" — You mostly can't revoke a live token; use short expiry plus refresh-token rotation, or a denylist if you must.
- "HS256 vs RS256?" — Symmetric shared secret vs asymmetric key pair; RS256 lets other services validate without holding the signing key.
- "What claim stops an expired token?" — The
expclaim, validated on every request.
Red flag: "JWTs are encrypted, so it's safe to put anything in them." They are not encrypted, and secrets in a payload are secrets published. This one sentence has ended interviews.
Next up: the data round
You can now hold your own on the web layer — pipeline, lifetimes, API design, and auth. But every .NET interview eventually turns to the database, because that's where real applications win or lose. In Part 6, we tackle SQL and EF Core: indexes, the N+1 problem, and the production-slowness question that quietly checks whether you think like a senior.