Interview questions

20 .NET Full Stack Developer Interview Questions for Mid-Level Candidates

July 22, 2025Updated May 9, 202622 min read
Are You Prepared To Dominate Your Next Interview As A Net Full Stack Developer

20 .NET full stack interview questions for mid-level candidates, with answer patterns, follow-up probes, and tradeoffs that show real experience.

Mid-level .NET interviews rarely go sideways because you forgot a definition. They go sideways because you gave a correct answer and then had nothing to say when the interviewer asked "why that way?" If you're preparing for .NET full stack developer interview questions at the mid-level, the gap isn't knowledge — it's the reasoning layer that makes knowledge sound like experience. This guide covers 20 questions across C#, EF Core, DI, JWT, SQL, and front-end async, and for each one it shows you what the follow-up looks like and what a production-grounded answer sounds like compared to a rehearsed one.

The difference matters more at mid-level than at any other point. Junior candidates get some slack for knowing the textbook version. Senior candidates get asked about system design. Mid-level candidates get asked the same questions as juniors, but the bar is whether the answer changes under pressure — whether you can tie a definition to a real decision, a real bug, or a real tradeoff you've navigated.

Which .NET full stack interview questions show up first at mid-level

The opening round of most .NET full stack developer interview questions is a filter, not a deep dive. Interviewers are checking whether your mental model of the language and runtime is connected to real code, or whether it stops at the glossary. The questions feel basic. The answers that pass are not.

Which C# basics are still worth asking at mid-level?

Overriding versus overloading, polymorphism, and interface basics still appear in mid-level interviews because they're fast to ask and immediately reveal how a candidate thinks about code structure. The definition of each is easy to find. The answer interviewers want is different: why would you choose one over the other in a real codebase?

Overloading is about giving a method multiple signatures in the same class — useful in utility layers where you want a clean API that accepts different input types without forcing the caller to convert. Overriding is about changing inherited behavior in a subclass — the right tool when a base service has a default implementation that one concrete type needs to replace. If your answer stops at the definition, the follow-up will be: "Give me a place in your last project where you made that call." Have one ready.

Which .NET runtime questions are really about experience?

CLR, garbage collection, and managed versus unmanaged code come up because interviewers want to know whether a candidate has ever cared about memory behavior in production — not whether they can recite what the CLR stands for. The real question behind "what is garbage collection?" is: "Have you ever seen it cause a problem?"

Strong answers mention the Gen 0/1/2 collection model, explain why object allocation patterns matter in high-throughput services, and at least acknowledge that finalizers and IDisposable exist for a reason. If you've used memory profiling tools or noticed GC pressure in a real app, say so. That one sentence of lived context does more work than two paragraphs of definition.

How much front-end should a full stack candidate expect?

More than most backend-leaning candidates prepare for. A full stack .NET role typically involves React or Angular, and interviewers will probe whether you understand async data loading, component state, and the API contract from the UI side. The tell is whether your answer about a fetch call stops at "I called the endpoint" or whether it covers loading state, error handling, and what happens when the response is slower than expected.

Candidates tend to over-prepare C# trivia and under-prepare the front-end async side. In real interviews, the front-end questions are often where mid-level candidates lose ground — not because the questions are harder, but because they've spent less time thinking through the full request path from the browser to the database and back.

Answer C# and OOP questions without sounding memorized

The trap with C# interview questions is that they have clean textbook answers, and clean textbook answers are exactly what interviewers have heard five hundred times. The goal is not to give a wrong answer — it's to give a correct answer that sounds like it came from a codebase rather than a flashcard.

How do you answer "overriding vs overloading" like you've used both?

The definition answer: overloading is same method name, different parameters; overriding is replacing a base class method in a derived class. That's correct. It's also the answer every candidate gives.

The working answer adds a scenario: "In a recent service layer, I had a base `NotificationService` with a virtual `Send` method. The email and SMS implementations overrode it because the delivery logic was completely different. Separately, I overloaded a `FormatMessage` helper to handle both string and object inputs without the caller having to know which." That answer demonstrates that you understand when each pattern earns its place — which is what the question is actually testing.

When does inheritance help, and when is it just baggage?

Inheritance is genuinely useful when derived types truly are specializations of the base type and when shared behavior in the base class would otherwise be duplicated across every subclass. The problem is that mid-level candidates often reach for inheritance as a default structure rather than a deliberate choice, and base classes accumulate methods that only apply to two of the five subclasses. That's when inheritance becomes a maintenance liability.

The answer interviewers want acknowledges both sides: "Inheritance made sense when I had three concrete report types that all needed the same validation and header logic. I put that in a base class. But when I tried to extend it for a fourth type that needed different validation, I ended up with a base class full of conditionals. That's when I refactored to composition with an interface." That answer shows judgment, not just vocabulary.

What makes a polymorphism answer sound like real engineering?

Polymorphism answers that stop at "objects of different types can be treated as the same base type" are technically correct and experientially empty. The engineering version ties it to an extension point: "We had three payment providers. Each implemented `IPaymentGateway`. The checkout service took an `IPaymentGateway` and didn't know or care which provider was injected. Adding a fourth provider was a new class, not a change to existing code." That answer demonstrates open/closed principle, dependency inversion, and polymorphism in one sentence — because in a real system, they show up together.

Microsoft's C# documentation covers the mechanics of virtual dispatch and method overriding precisely — worth reading before an interview to make sure your terminology matches the language specification.

Interface vs abstract class is the question interviewers use to test judgment

This comparison appears in almost every mid-level .NET interview because it has a short definition answer and a much longer judgment answer. The candidates who pass the follow-up are the ones who can say when each choice causes problems.

What do interviewers really want to hear about interfaces?

The real answer is about contracts, seams, and testability — not syntax. An interface defines a contract that any type can fulfill, which means you can swap implementations without changing the consumer. The practical payoff: you can inject a mock `IEmailSender` in tests and a real `SmtpEmailSender` in production, and the service that uses it never changes. The interviewer wants to hear that you understand the interface as a design boundary, not just as a feature of the language.

Concrete scenario: "We had a file storage interface with S3 and local disk implementations. Switching the production provider was a DI registration change. The service layer was untouched." That's the answer.

When is an abstract class the better production choice?

When you have shared behavior that all subtypes genuinely need, and that behavior is non-trivial to duplicate. An abstract class lets you put real method implementations in the base, enforce a template method pattern, and still require subclasses to fill in the specific parts. The line between "useful shared base" and "dumping ground" is whether every method in the base class applies to every subclass. If it doesn't, you're already in trouble.

The failure case worth mentioning: a base `ReportGenerator` class that accumulated export, scheduling, and notification logic over two years because it was the easiest place to add things. By the time the team needed a new report type, the base class had seventeen methods, four of which were only used by one subclass. That's a real maintenance cost, and naming it in an interview answer signals that you've seen what bad abstraction looks like.

Why do so many candidates get trapped by this comparison?

Because the basic definition is easy to learn and sounds complete: "Interfaces can't have implementation, abstract classes can." That was even true before C# 8 added default interface members. The trap is that interviewers aren't asking about the syntax difference — they're asking about the design difference. The follow-up is always something like: "Your team is building a new data access layer. Which would you use and why?" A definition-shaped answer has nowhere to go from there. A judgment-shaped answer has a whole conversation ahead of it.

Microsoft's guidance on choosing between interfaces and abstract classes is the authoritative reference here and worth reading for the exact framing the .NET team uses.

Explain dependency injection, lifetimes, and middleware in plain English

Dependency injection is the topic where candidates most often know the term, can define it correctly, and still give an answer that sounds like a documentation summary. The plain-English version is more useful and more memorable.

What is dependency injection without the buzzwords?

DI is moving object creation out of your business logic. Instead of a `UserService` constructing its own `UserRepository` with `new UserRepository()`, the repository is passed in — usually through the constructor. The service doesn't know how the repository was built, only what it can do. That separation means you can swap implementations, mock dependencies in tests, and change infrastructure choices without touching business logic.

The one-sentence version: "DI means your class asks for what it needs instead of building it." If you can explain it that way and then immediately give an example — "so our `OrderService` takes an `IOrderRepository` in the constructor, and in tests we pass a mock, in production we pass the EF Core implementation" — you've answered the question and the follow-up at the same time.

How do service lifetimes show up in bugs?

Singleton, scoped, and transient lifetimes are easy to define. The bugs they cause are what interviewers actually want to discuss. A singleton service lives for the application lifetime. A scoped service lives for one HTTP request. A transient service is created fresh every time it's requested.

The classic production bug: a singleton service that captures a scoped dependency — like a `DbContext` — in its constructor. The `DbContext` was meant to be per-request. Captured inside a singleton, it lives forever, accumulates tracked entities, and eventually throws concurrency exceptions that are nearly impossible to reproduce locally. ASP.NET Core will actually warn you about this at startup in most cases, but knowing why it's a problem is the answer interviewers want.

How do you explain middleware to someone who ships APIs?

The middleware pipeline is the sequence of components that process every HTTP request before it reaches your controller and every response before it leaves. Each middleware component can inspect, modify, short-circuit, or pass the request along. Order matters: authentication middleware has to run before authorization middleware, and exception-handling middleware should be first so it can catch errors thrown by everything downstream.

Concrete example: "Our pipeline had exception handling first, then HTTPS redirection, then authentication, then a custom request logging middleware, then routing. When we moved the logging middleware before authentication, it started logging requests that hadn't been validated yet — including some with malformed tokens. Order isn't cosmetic."

Microsoft's ASP.NET Core middleware documentation covers the pipeline order and built-in middleware precisely — the diagrams there are worth having in your head before an interview.

EF Core questions are really about query shape and performance

EF Core interview questions almost always have a performance angle. The interviewer is not checking whether you know how to write a LINQ query — they're checking whether you know what happens to that query when it runs against a real database with real data volumes.

IEnumerable vs IQueryable: what's the actual difference here?

`IQueryable` builds an expression tree that gets translated to SQL and executed at the database. `IEnumerable` operates on in-memory data. The practical consequence: if you call `.Where()` on an `IQueryable`, the filter runs in SQL and only the matching rows come back. If you accidentally force evaluation early — by calling `.ToList()` before the filter, or by returning `IEnumerable` from a repository method — the filter runs in memory after pulling every row from the table.

This is the kind of bug that works fine in development with 200 rows and falls apart in production with 2 million. The answer interviewers want names the mechanism: "The query isn't sent until it's materialized. If I return `IQueryable` from the repository, the calling layer can still compose filters. If I return `IEnumerable`, the query has already run."

When should you track entities, and when should you not?

EF Core tracks entities by default, which means it maintains a snapshot of every object returned from a query so it can detect changes and generate UPDATE statements. For write operations, that's exactly what you want. For read-heavy APIs that return data without modifying it, tracking is pure overhead — memory and CPU spent on change detection that will never be used.

`.AsNoTracking()` is the right call for any query where you're reading to display, not reading to update. The follow-up interviewers usually ask: "What breaks if you use no-tracking and then try to update the entity?" The answer: you need to either re-attach the entity or use a separate tracked query for the update. Knowing the tradeoff is the point.

What EF Core performance trap do interviewers expect you to catch?

N+1 queries. You load a list of orders, then for each order you load the customer. If EF Core isn't configured to eager-load the relationship, it generates one query for the order list and then one query per order for the customer — which means 101 database round trips for a page of 100 orders. The fix is `.Include(o => o.Customer)`, but the answer interviewers want goes further: "I found it by logging the generated SQL. In development it was invisible because the dataset was small. In production, the endpoint was timing out."

Microsoft's EF Core performance documentation covers query translation, tracking behavior, and loading strategies with concrete guidance — the section on efficient querying is directly relevant to interview questions at this level.

JWT auth and API security questions need more than a definition

ASP.NET Core interview questions about authentication almost always land on JWT. The definition is easy. The follow-up — about token validation, refresh flows, and what happens when a token is stolen — is where the answer needs to hold up.

What does a strong JWT answer actually cover?

A JWT is a signed token that encodes claims — user ID, roles, expiry — and is verified by the API using the signing key. The server doesn't store session state; it trusts the token if the signature is valid and the token hasn't expired. The interviewer wants to hear that you understand the trust model: the API trusts the token because it trusts the key, not because it remembers issuing the token.

The follow-up is almost always: "What happens if the token is compromised before it expires?" The honest answer is that short expiry times limit the damage window, and refresh tokens provide a way to revoke access without requiring the user to log in again — but there's no perfect solution, only tradeoffs.

Where do refresh tokens and secure storage come in?

Access tokens are short-lived — typically 15 minutes to an hour. Refresh tokens are longer-lived and stored server-side, which means they can be revoked. When the access token expires, the client uses the refresh token to get a new one without prompting the user. The security tradeoff: if you store the refresh token in localStorage, XSS can steal it. HttpOnly cookies are harder to steal but require CSRF protection. Neither is free.

The answer that impresses interviewers names the tradeoff explicitly: "We used HttpOnly cookies for the refresh token and short-lived JWTs in memory. It's not perfect, but it limits the XSS exposure without opening a CSRF hole we hadn't thought through."

How do you talk about API security without sounding hand-wavy?

Cover the concrete layer: HTTPS everywhere, authorization checks on every endpoint (not just authentication), token lifetime calibrated to the sensitivity of the data, and rate limiting on auth endpoints to slow down brute-force attempts. Then connect it to a real endpoint: "On our payments endpoint, we checked the user's role claim, verified the user ID in the token matched the resource being accessed, and kept the token lifetime at 15 minutes. We also logged every failed authorization attempt."

OWASP's REST Security Cheat Sheet is the authoritative reference for API security best practices and is worth citing if you're asked where your security knowledge comes from.

SQL and indexing questions are where production judgment shows up

SQL interview questions at mid-level are almost never about syntax. They're about whether you understand what the database is doing with your query — and whether you've ever had to care.

What does a useful indexing answer sound like?

An index speeds up reads by maintaining a sorted structure the database can search without scanning every row. The cost is write overhead and storage. The answer interviewers want goes further: "I added a composite index on `(user_id, created_at)` on our orders table because the most common query filtered by user and sorted by date. Without the index, that query was doing a full table scan. With it, the execution plan showed an index seek."

The follow-up is usually: "How do you decide which columns to index?" The answer: look at the queries that run most frequently and are slowest, check the WHERE and ORDER BY clauses, and avoid indexing columns with very low cardinality because the selectivity isn't worth the overhead.

How do you talk through a slow query?

The sequence matters: start with the query shape — are you selecting more columns than you need, joining more tables than necessary? Then look at the WHERE clause — is the filter sargable, or does it wrap a column in a function that prevents index use? Then pull the execution plan and look for table scans, key lookups, and high estimated row counts that don't match reality. Then check statistics freshness.

The answer that signals real experience: "I had a query that was fine in staging and slow in production. The execution plan looked identical. The difference was stale statistics — the optimizer thought the table had 10,000 rows, but it had 4 million. Updating statistics fixed it."

What database tradeoffs matter in a full stack role?

Pagination, caching, and concurrency all connect database choices to user-facing behavior. Offset-based pagination degrades at high page numbers because the database still scans all the skipped rows — keyset pagination is faster but requires a stable sort key. Caching query results at the application layer reduces database load but introduces staleness. Optimistic concurrency with row versioning avoids lock contention but requires the application to handle conflict resolution.

Naming these tradeoffs shows that you understand the database as part of the system, not as an isolated layer.

Front-end async questions still matter in a .NET full stack interview

Full stack .NET interview prep that ignores the front-end side is incomplete. React and Angular async patterns come up in interviews specifically because they reveal whether a candidate understands the full request path or just the backend half of it.

How do you explain promises and async/await without drifting into frontend jargon?

The core idea: async/await lets you wait for work — like an API call — without blocking the UI thread. The browser can keep rendering while the fetch is in flight. `await` is syntactic sugar over a Promise chain; the behavior is the same, but the code reads like synchronous flow.

The practical framing: "When a user submits a form, I await the POST request, show a loading state while it's in flight, handle the success response to update the UI, and catch errors to show a message. The user sees feedback at every stage instead of a frozen interface."

What does a good answer sound like when state updates lag?

Stale state and race conditions are the real async bugs in React and Angular. The scenario: a user types quickly in a search field, triggering multiple API calls. The second call resolves before the first, and the UI shows stale results. The fix is either canceling the earlier request with an AbortController or tracking which request is the latest and ignoring earlier responses.

The answer interviewers want names the failure mode: "I had a typeahead search that showed wrong results intermittently. The API calls were racing. I added a debounce and an AbortController on each new keystroke. The bug went away." That answer is specific, and specificity is the signal.

How do you connect front-end async to backend API design?

Loading states, error shapes, and retry behavior on the front end are all downstream consequences of how the API is designed. If the API returns a generic 500 with no body, the front end can't show a useful error message. If a paginated endpoint doesn't return total counts, the UI can't build accurate pagination controls. If the API is slow because of an N+1 query, the front-end loading state looks broken even though the UI code is correct.

The React documentation on data fetching and the Angular docs on HttpClient both cover async patterns in enough depth to give you concrete examples before an interview.

Use follow-up questions to prove you've actually done the work

Mid-level .NET interview questions are designed to have a follow-up. The first answer establishes whether you know the concept. The follow-up establishes whether you've used it. Preparing for the follow-up is the actual preparation.

What follow-up probes usually come after a solid answer?

The most common probes are: "Why did you make that choice over the alternative?", "What breaks if the load doubles?", "How would you test that?", and "What would you change if you built it again?" These aren't trick questions. They're the natural next step when an interviewer wants to distinguish someone who read about a pattern from someone who shipped it.

Prepare for each answer you practice by asking yourself those four questions out loud. If you can't answer them, your first answer isn't ready either.

What does a strong answer look like when the interviewer pushes back?

It shifts from definition mode to reasoning mode. If you said "I'd use a singleton for the caching service," and the interviewer says "what if the cache holds user-specific data?", the strong answer is: "Then singleton is the wrong lifetime — it would share state across requests. I'd rethink whether the cache should be scoped or whether user-specific data belongs in a distributed cache outside the DI container entirely." That answer shows that you understand the constraint, can reason about the consequence, and know what the alternative is.

How do you separate memorized knowledge from real experience fast?

Real experience includes tradeoffs, mistakes, and operational consequences. Memorized answers stop at the first sentence. If someone can define JWT but can't say what happens when the signing key rotates, they've memorized the definition. If they can explain that you need to support both the old and new key during a rolling rotation window to avoid invalidating all active sessions, they've operated a system that uses JWT.

In hiring discussions, the follow-up question "what went wrong the first time you used this?" is one of the clearest separators. Candidates with real experience have a story. Candidates with rehearsed knowledge have a pause.

How Verve AI Can Help You Ace Your Coding Interview With .NET

The gap this article keeps returning to — knowing the answer but collapsing under the follow-up — is a practice problem, not a knowledge problem. You can read every definition of DI lifetimes and still give a flat answer when the interviewer asks what breaks if you use a singleton for a scoped dependency. The only way to close that gap is to rehearse the follow-up, out loud, against a system that responds to what you actually said.

Verve AI Coding Copilot is built for exactly that scenario. It reads your screen in real time — whether you're working through a LeetCode problem, a HackerRank challenge, or a live technical round — and responds to what you've actually written or said, not a canned prompt. If your EF Core query has an N+1 pattern, Verve AI Coding Copilot can surface it before the interviewer does. If your DI registration has a lifetime mismatch, it flags the consequence, not just the syntax. The Secondary Copilot feature keeps you focused on a single problem without context-switching, which matters in timed rounds where losing the thread is as costly as getting the answer wrong. Verve AI Coding Copilot works across LeetCode, HackerRank, CodeSignal, and live technical interviews — and it stays invisible while it does. The goal isn't to answer for you. It's to make sure the follow-up doesn't catch you empty-handed.

Conclusion

The mid-level .NET interview problem isn't a knowledge gap. You already know what dependency injection is, what JWT stands for, and how EF Core queries work. The problem is that your answers are built to survive the first question, not the second. Every section in this guide was written to give you a version of each answer that holds up when the interviewer pushes — because that's the actual test.

Use this question set as a drill, not a reading list. Take each question, give your answer out loud, then immediately ask yourself the follow-up: "Why that way? What breaks? How would you test it?" The answer that survives those three questions is the answer that gets you to the next round.

JE

Jordan Ellis

Interview Guidance

Ace your live interviews with AI support!

Get Started For Free

Available on Mac, Windows and iPhone