Skip to content

.NET Full Stack Interview Questions & Answers

All 200 unique questions in one place — 63 easy, 94 medium, 43 hard — grouped by topic.

Practise by topic

Solved overallStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is the difference between .NET Framework, .NET Core and modern .NET?

Save to ▾
Show answer
.NET Framework is the original Windows-only runtime, now in maintenance mode at version 4.8.1. .NET Core was the cross-platform, open-source rewrite. From .NET 5 onwards the name became just .NET, and it runs on Windows, Linux and macOS. In 2026, .NET 10 is the current LTS release. New projects should use modern .NET; Framework is kept only for legacy apps such as old Web Forms or WCF services.
02

What is the CLR and what does it do?

Save to ▾
Show answer
The Common Language Runtime is the execution engine of .NET. It loads compiled IL code, converts it to machine code with the JIT compiler, manages memory through the garbage collector, enforces type safety, handles exceptions and manages threads. Because every .NET language compiles to the same IL, C#, F# and VB.NET code can run on the same CLR and call each other.
03

Explain value types and reference types in C#.

Save to ▾
Show answer
Value types such as int, double, bool, enums and structs hold their data directly, and assigning one copies the value. Reference types such as classes, arrays, strings and delegates hold a reference to an object on the managed heap, so assigning copies only the reference. Changing a copied struct does not affect the original, but changing an object through a copied reference changes what both variables see.
04

What are boxing and unboxing?

Save to ▾
Show answer
Boxing converts a value type to object or an interface type by wrapping it in a heap object, for example object o = 42. Unboxing extracts the value back with an explicit cast, such as int n = (int)o. Both cost allocations and CPU time, and repeated boxing in loops increases garbage collection pressure. Generic collections like List<int> avoid boxing, which is one reason ArrayList is no longer used.
05

When should you use StringBuilder instead of string?

Save to ▾
Show answer
Strings in C# are immutable, so every concatenation creates a new string object and copies the old content. In a loop that appends thousands of times, this creates heavy allocations. StringBuilder keeps a resizable internal buffer and appends in place, so it is much faster for repeated changes. For two or three concatenations or interpolation in a single statement, a normal string is simpler and fine.
06

Write an extension method that checks whether a string is a valid Indian mobile number.

Save to ▾
Show answer
public static class StringExtensions { public static bool IsIndianMobile(this string? value) => value is not null && System.Text.RegularExpressions.Regex.IsMatch(value, @"^[6-9]\d{9}$"); } // usage bool ok = "9876543210".IsIndianMobile(); Extension methods are static methods in a static class whose first parameter uses this, so they appear like instance methods.
07

What is the difference between var, dynamic and object?

Save to ▾
Show answer
var is implicitly typed: the compiler infers the real type at compile time, so it is fully type-safe. object is the base type of everything; you need casts to use specific members, and value types get boxed. dynamic skips compile-time checking and resolves members at runtime, so typos fail only when the code runs. Use var for readability, object rarely, and dynamic only for COM interop or truly dynamic data.
08

A report builder concatenates 50,000 rows into one string with += and takes several seconds. What do you change?

Save to ▾
Show answer
Each += creates a new string and copies everything built so far, so the cost grows quadratically. Replace it with a StringBuilder, ideally created with an estimated capacity, and call Append or AppendLine in the loop, then ToString once at the end. For very large output, write directly to a StreamWriter or the response stream instead of building the whole string in memory.
09

Write a C# method to reverse a string without using Array.Reverse or LINQ.

Save to ▾
Show answer
static string ReverseText(string input) { char[] chars = input.ToCharArray(); int left = 0, right = chars.Length - 1; while (left < right) { (chars[left], chars[right]) = (chars[right], chars[left]); left++; right--; } return new string(chars); } Two pointers swap from both ends, giving O(n) time and O(n) space for the char array.
10

Tell me about a time you had to learn a new C# or .NET feature quickly.

Save to ▾
Show answer
In my final-year project (Situation) our team needed async file uploads, but I only knew synchronous code. My task was to build the upload API within a week. I read the official async/await docs, built a small console demo, then refactored our controller to use async methods and IFormFile streaming. The result was uploads that no longer blocked requests, and I shared a short note with my team.
11

Why do you want to work as a .NET full stack developer?

Save to ▾
Show answer
I enjoy building complete features, from database to screen, and .NET lets me do that with one strong, typed language on the back end. It is widely used by IT services firms, banks and product companies in India, so there are steady opportunities. I have built projects with ASP.NET Core and React, and I like that the platform is open source, cross-platform and keeps improving every year.
12

What is the difference between const, readonly and static readonly?

Save to ▾
Show answer
const is a compile-time constant, implicitly static, and its value is copied into calling assemblies, so changing it requires recompiling them. readonly fields are set at declaration or in the constructor and can differ per instance. static readonly is set once per type at runtime, so it can hold values like DateTime.Now or a new object. Use const only for values that will never change, such as Math.PI.
13

Explain the ref, out and in parameter modifiers.

Save to ▾
Show answer
ref passes a variable by reference; it must be initialised before the call and the method can read and change it. out also passes by reference but need not be initialised, and the method must assign it before returning, as in int.TryParse. in passes by reference as read-only, which avoids copying large structs while preventing changes. Overusing ref and out makes code harder to read, so tuples are often cleaner.
14

What are nullable value types and nullable reference types?

Save to ▾
Show answer
Nullable value types like int? wrap a struct so it can hold null, with HasValue and Value properties. Nullable reference types, enabled by <Nullable>enable</Nullable>, are a compile-time feature: string means non-null and string? means may be null, and the compiler warns when you dereference a possible null. They do not change runtime behaviour but catch many NullReferenceException bugs before deployment.
15

Show how to implement IDisposable and use the using statement.

Save to ▾
Show answer
public class FileLogger : IDisposable { private readonly StreamWriter _writer = new("log.txt"); public void Log(string msg) => _writer.WriteLine(msg); public void Dispose() => _writer.Dispose(); } // using declaration disposes at end of scope using var logger = new FileLogger(); logger.Log("Started"); Dispose releases unmanaged resources such as file handles and connections deterministically instead of waiting for the GC.
16

What is the difference between == and Equals() in C#?

Save to ▾
Show answer
For reference types, == by default checks reference equality, meaning both variables point to the same object, while Equals can be overridden to compare content. String overrides both, so == compares text. For value types, Equals compares field values. Records generate value-based equality automatically. When you override Equals, also override GetHashCode so objects behave correctly in dictionaries and hash sets.
17

What are record types and when would you use them?

Save to ▾
Show answer
Records are reference types (or record struct for value types) designed for immutable data. The compiler generates value-based equality, a readable ToString, a deconstructor and support for with-expressions that create a modified copy. A positional record is one line: public record Order(int Id, decimal Total). They suit DTOs, API responses, events and value objects, but not EF Core entities that need change tracking by identity.
18

You are designing a type to hold a 2D point used millions of times in a calculation. Struct or class?

Save to ▾
Show answer
A struct is a good fit because the point is small, logically a single value and created in huge numbers. Structs avoid heap allocation and GC pressure when stored in arrays or locals. Make it a readonly struct so it is immutable and avoids defensive copies. Choose a class instead if the type is large, needs inheritance, or is frequently boxed through interfaces, since copying and boxing remove the benefit.
19

Write a switch expression using pattern matching to calculate shipping cost.

Save to ▾
Show answer
decimal Shipping(Order o) => o switch { { Total: >= 1000 } => 0m, { Country: "IN", Weight: < 2 } => 49m, { Country: "IN" } => 99m, { Weight: > 20 } => throw new ArgumentException("Too heavy"), _ => 499m }; Property and relational patterns replace long if-else chains, and the compiler warns if cases are not exhaustive.
20

What is the difference between throw and throw ex inside a catch block?

Save to ▾
Show answer
throw rethrows the current exception and preserves the original stack trace, so logs show where the error really started. throw ex resets the stack trace to the catch block, hiding the real source. Always use throw when rethrowing. If you need more context, wrap it: throw new OrderException("Payment failed", ex), which keeps the original as InnerException. Also avoid catching Exception unless you log and rethrow.
21

Show a class using a primary constructor with dependency injection.

Save to ▾
Show answer
public class OrderService(IOrderRepository repo, ILogger<OrderService> logger) { public async Task<Order?> GetAsync(int id) { logger.LogInformation("Fetching order {Id}", id); return await repo.FindAsync(id); } } Primary constructors on classes arrived in C# 12. Parameters are captured and usable in all members, removing boilerplate fields. They are not readonly, so assign to a readonly field if immutability matters.
22

How does garbage collection work in .NET and what are generations?

Save to ▾
Show answer
The GC automatically frees objects that are no longer reachable from roots such as static fields, locals and CPU registers. The heap is split into generations: Gen 0 for new short-lived objects, Gen 1 as a buffer, and Gen 2 for long-lived objects. Most objects die young, so Gen 0 collections are frequent and cheap. Objects over 85,000 bytes go to the Large Object Heap, which is collected with Gen 2.
23

What are Span<T> and Memory<T> and why do they matter for performance?

Save to ▾
Show answer
Span<T> is a ref struct that represents a contiguous slice of memory, such as part of an array, a string or stack memory, without copying it. Slicing a span is free, which makes parsing much faster with zero allocations. Because it is stack-only, it cannot be stored in fields or used across await. Memory<T> is the heap-storable version for async code. ASP.NET Core and System.Text.Json use them heavily.
24

A .NET API's memory keeps growing in production until the pod restarts. How do you investigate?

Save to ▾
Show answer
First confirm with metrics using dotnet-counters: watch GC heap size, Gen 2 count and LOH size. Then capture a heap dump with dotnet-gcdump or dotnet-dump and compare two dumps over time to find which object types keep growing and what roots hold them. Common causes are static caches without expiry, event handlers never unsubscribed, undisposed HttpClient or DbContext, and singletons capturing scoped services. Fix the root, then load test.
25

What is the difference between JIT compilation and Native AOT in .NET?

Save to ▾
Show answer
With JIT, the app ships as IL and the runtime compiles methods to machine code when first called; tiered compilation later recompiles hot methods with better optimisation. Native AOT compiles everything ahead of time into a single native executable, giving very fast startup and lower memory, which suits containers and serverless. The trade-off is limited reflection and dynamic code generation, so some libraries need source generators to work.
26

What are the four pillars of object-oriented programming?

Save to ▾
Show answer
Encapsulation hides internal state behind methods and properties. Abstraction exposes only what the caller needs, using abstract classes and interfaces. Inheritance lets a class reuse and extend another class. Polymorphism lets one interface have many implementations, so code calls Pay() without knowing whether it is a card or UPI payment. Together they make code easier to change, test and reuse.
27

What is the difference between an abstract class and an interface in C#?

Save to ▾
Show answer
An abstract class can have fields, constructors, implemented and abstract members, and a class can inherit only one. An interface defines a contract; a class can implement many. Since C# 8, interfaces can have default method implementations but still no instance fields. Use an abstract class for shared state and base behaviour among closely related types, and interfaces for capabilities like IComparable or for dependency injection.
28

What is the difference between method overloading and method overriding?

Save to ▾
Show answer
Overloading means several methods with the same name but different parameter lists in the same class, resolved at compile time, for example Add(int, int) and Add(double, double). Overriding means a derived class provides a new implementation of a virtual or abstract base method with the same signature, resolved at runtime based on the actual object type. Overloading is compile-time polymorphism; overriding is runtime polymorphism.
29

What does the sealed keyword do?

Save to ▾
Show answer
A sealed class cannot be inherited, and a sealed override method cannot be overridden further in derived classes. Use it when a class is not designed for extension, such as a security-sensitive or immutable type; string is sealed for this reason. Sealing also lets the JIT devirtualise calls, giving small performance gains. Many teams seal classes by default and unseal only when inheritance is genuinely needed.
30

Show constructor chaining in C#.

Save to ▾
Show answer
public class Customer { public string Name { get; } public string City { get; } public Customer(string name) : this(name, "Unknown") { } public Customer(string name, string city) { Name = name; City = city; } } public class PremiumCustomer : Customer { public PremiumCustomer(string name) : base(name, "Delhi") { } } this() calls another constructor of the same class and base() calls the parent constructor, avoiding duplicated setup code.
31

What is the difference between compile-time and runtime polymorphism?

Save to ▾
Show answer
Compile-time, or static, polymorphism is resolved by the compiler, mainly through method overloading and operator overloading, and through generics. Runtime, or dynamic, polymorphism is resolved when the program runs, through virtual methods and interfaces: a Shape reference may call Circle.Area or Square.Area depending on the actual object. Runtime polymorphism is what makes plugin designs and dependency injection possible.
32

Show encapsulation using properties, including init-only and validation.

Save to ▾
Show answer
public class BankAccount { public string AccountNo { get; init; } = ""; public decimal Balance { get; private set; } public void Deposit(decimal amount) { if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount)); Balance += amount; } } var acc = new BankAccount { AccountNo = "SB1001" }; Balance can only change through Deposit, and AccountNo can be set only during object creation.
33

What are partial classes and partial methods?

Save to ▾
Show answer
A partial class splits one class definition across multiple files, and the compiler merges them. It is used heavily with generated code: designers, EF Core scaffolding and source generators write one part while you write the other, so regeneration does not erase your code. Partial methods declare a signature in one part and an optional implementation in another; since C# 9 they can have return types and access modifiers if implemented.
34

You need to add a new method to a widely implemented interface without breaking existing classes. How can you do it?

OOP in C#Medium
Save to ▾
Show answer
Since C# 8, an interface can provide a method body. Classes implementing the interface get that behaviour without writing it, though they can override it. The main use is evolving a published interface: you can add a new member without breaking every existing implementation. The default method is only callable through the interface type, not the class, and overusing it blurs the line with abstract classes.
35

Explain the virtual, override and new keywords.

OOP in C#Medium
Save to ▾
Show answer
virtual marks a base method as replaceable. override in a derived class replaces it, so calls through a base reference run the derived version. new hides the base method instead: a call through a base reference still runs the base version, and only a derived-type reference sees the new one. Method hiding is usually a sign of a design problem, and the compiler warns when you hide without writing new.
36

Explain the access modifiers in C#, including protected internal and private protected.

OOP in C#Medium
Save to ▾
Show answer
public is accessible everywhere, private only inside the type, protected inside the type and derived types, and internal anywhere in the same assembly. protected internal means accessible from the same assembly or from derived types in any assembly. private protected is stricter: only derived types inside the same assembly. Class members default to private and top-level types default to internal. Use the narrowest modifier that works.
37

What is the difference between a static class and a singleton?

OOP in C#Medium
Save to ▾
Show answer
A static class cannot be instantiated, cannot implement interfaces and is initialised by the runtime; it suits stateless helpers like Math. A singleton is a normal class with exactly one instance, so it can implement interfaces, be passed as a parameter and be mocked in tests. In ASP.NET Core, you rarely write a singleton by hand; you register the class with AddSingleton and let the DI container manage its lifetime.
38

Explain the SOLID principles briefly.

OOP in C#Medium
Save to ▾
Show answer
Single Responsibility: a class has one reason to change. Open/Closed: extend behaviour without editing existing code. Liskov Substitution: derived types must work wherever the base type is expected. Interface Segregation: prefer small, focused interfaces over one fat interface. Dependency Inversion: depend on abstractions, not concrete classes. In ASP.NET Core, injecting IEmailSender into a controller instead of creating SmtpClient directly applies dependency inversion.
39

Show an example of the Dependency Inversion Principle in C#.

OOP in C#Medium
Save to ▾
Show answer
public interface INotifier { Task SendAsync(string to, string msg); } public class SmsNotifier : INotifier { public Task SendAsync(string to, string msg) => Task.CompletedTask; // call SMS API } public class OrderService(INotifier notifier) { public Task ConfirmAsync(Order o) => notifier.SendAsync(o.Phone, "Order placed"); } // Program.cs builder.Services.AddScoped<INotifier, SmsNotifier>(); OrderService depends on the abstraction, so you can swap to email or a mock without changing it.
40

A teammate created a deep inheritance chain Employee > Manager > SeniorManager > RegionalHead to add features. What would you suggest?

OOP in C#Medium
Save to ▾
Show answer
Deep hierarchies are fragile: a change in a base class ripples into every child, and behaviours that do not fit the tree get duplicated. I would suggest composition over inheritance. Keep a single Employee entity and give it composed parts such as a Role, an ApprovalPolicy and a list of Permissions, injected as interfaces. New behaviour then means a new policy class, not a new subclass, which is easier to test.
41

What is a delegate in C#?

OOP in C#Medium
Save to ▾
Show answer
A delegate is a type-safe reference to a method with a specific signature, similar to a function pointer but checked by the compiler. You can pass methods as parameters, store them and call them later. Delegates can be multicast, holding several methods that run in order. Lambdas, LINQ, events and callbacks are all built on delegates, and the built-in Func and Action types cover most needs.
42

How are events different from plain delegates?

OOP in C#Medium
Save to ▾
Show answer
An event is a delegate wrapped with restricted access. Outside the class, subscribers can only add or remove handlers with += and -=; they cannot invoke the event or overwrite the whole list with =. This protects the publisher. The standard pattern uses EventHandler<TEventArgs> with sender and args. Remember to unsubscribe long-lived subscriptions, otherwise the publisher keeps subscribers alive and causes memory leaks.
43

Show how Func, Action and Predicate are used.

OOP in C#Medium
Save to ▾
Show answer
Func<decimal, decimal> addGst = price => price * 1.18m; Action<string> log = msg => Console.WriteLine($"[LOG] {msg}"); Predicate<int> isAdult = age => age >= 18; decimal total = addGst(1000m); // 1180 log($"Total {total}"); bool ok = isAdult(21); // true Func returns a value (last type argument is the return type), Action returns void, and Predicate<T> returns bool. They save you from declaring custom delegate types.
44

Which design patterns do you commonly see in ASP.NET Core projects?

OOP in C#Medium
Save to ▾
Show answer
Dependency Injection is built in. The Repository and Unit of Work patterns wrap data access, although DbContext already implements them. Factory creates objects by type, for example IHttpClientFactory. Strategy swaps algorithms, such as different tax or discount rules, behind one interface. Options pattern binds configuration to classes. Middleware is a Chain of Responsibility, and Mediator libraries implement CQRS by sending commands to handlers.
45

What is the difference between a shallow copy and a deep copy?

OOP in C#Medium
Save to ▾
Show answer
A shallow copy duplicates the object but its reference fields still point to the same child objects; MemberwiseClone and record with-expressions do this. A deep copy duplicates the whole object graph, so changes to the copy never affect the original. Deep copies are usually written by hand or by serialising and deserialising. ICloneable is avoided because it does not say which kind of copy it returns.
46

Tell me about a time you refactored messy code that others depended on.

OOP in C#Medium
Save to ▾
Show answer
In my last project (Situation) an invoice module had one 900-line class with duplicated GST logic. My task was to add a new tax rule without breaking billing. I first wrote unit tests around current behaviour, then extracted tax rules into strategy classes and moved data access into a repository, merging in small pull requests. Result: the new rule took one day, and bugs in that module dropped noticeably the next quarter.
47

How do you explain good object-oriented design to a junior developer on your team?

OOP in C#Medium
Save to ▾
Show answer
I avoid theory first. I take a real piece of our code, like a controller that talks to the database directly, and pair with them to move logic into a service behind an interface, then write a unit test with a mock. Seeing how much easier testing becomes explains SOLID better than slides. I then review their next pull request with specific comments and point them to one or two good examples in our codebase.
48

A PaymentService has a large if-else on payment type (card, UPI, netbanking, wallet) and every new method means editing it. How do you refactor?

Save to ▾
Show answer
Apply the Strategy pattern with the Open/Closed principle. Define IPaymentProcessor with a Type property and ProcessAsync method, and create one class per method. Register all of them in DI, inject IEnumerable<IPaymentProcessor>, and pick the right one by type, possibly through a dictionary. Adding a new payment type is now a new class plus a registration, with no change to existing, tested code.
49

Write a thread-safe singleton in C#.

Save to ▾
Show answer
public sealed class AppConfig { private static readonly Lazy<AppConfig> _instance = new(() => new AppConfig()); public static AppConfig Instance => _instance.Value; private AppConfig() { // load settings once } } Lazy<T> is thread-safe by default and creates the object only on first access. The private constructor and sealed class prevent other instances. In ASP.NET Core, prefer AddSingleton.
50

Give an example of a Liskov Substitution Principle violation and how to fix it.

Save to ▾
Show answer
A classic case is Square inheriting Rectangle. Setting Width on a square also changes Height, so code that sets width 5 and height 4 and expects area 20 breaks. Another real case is a ReadOnlyRepository that inherits Repository and throws NotSupportedException on Save. The fix is to model shared behaviour with interfaces such as IShape or IReadRepository and IWriteRepository, so subclasses never weaken the contract.
51

What is LINQ and why is it useful?

Save to ▾
Show answer
LINQ, Language Integrated Query, lets you query collections, databases, XML and other sources with the same C# syntax using methods like Where, Select, OrderBy and GroupBy. Queries are type-checked at compile time and read close to the intent, for example orders.Where(o => o.Total > 500).OrderBy(o => o.Date). With EF Core, the same LINQ expression is translated into SQL, so you rarely write raw SQL strings.
52

When would you choose an array, a List<T> or a LinkedList<T>?

Save to ▾
Show answer
An array has a fixed size and fastest index access, good when the count is known. List<T> wraps a resizable array, with O(1) index access and amortised O(1) add at the end, and is the default choice for most code. LinkedList<T> gives O(1) insert and remove at a known node but O(n) access by index and poor cache locality, so it is rarely the better option in practice.
53

When would you use a HashSet<T>?

Save to ▾
Show answer
HashSet<T> stores unique values with O(1) average lookup, add and remove. Use it when you need fast membership checks, such as checking if an email already exists in a batch of 1 lakh records, or to remove duplicates. It also supports set operations like UnionWith, IntersectWith and ExceptWith. It does not keep insertion order or allow index access; use SortedSet<T> if you need sorted unique values.
54

Explain First, FirstOrDefault, Single and SingleOrDefault.

Save to ▾
Show answer
First returns the first match and throws if none exists. FirstOrDefault returns the default value, null for classes, if none exists. Single expects exactly one match and throws if there are zero or more than one. SingleOrDefault returns default for zero but still throws for more than one. Use Single when duplicates would indicate a data bug, such as lookup by unique PAN number; otherwise FirstOrDefault is cheaper.
55

Find the second highest salary from a list using LINQ.

Save to ▾
Show answer
int? second = employees .Select(e => e.Salary) .Distinct() .OrderByDescending(s => s) .Skip(1) .Cast<int?>() .FirstOrDefault(); Distinct handles ties, so if two people earn the top salary the next lower value is returned. Casting to int? makes the result null instead of 0 when fewer than two distinct salaries exist.
56

What are generics and what benefits do they give?

Save to ▾
Show answer
Generics let you write classes and methods with a type parameter, such as List<T> or Repository<T>, that work with any type while staying type-safe. Benefits are compile-time checking instead of casts, no boxing for value types, and code reuse. For example, one generic Result<T> type can wrap any API response. The CLR creates specialised code for value types and shares code for reference types.
57

Why is Any() usually better than Count() > 0?

Save to ▾
Show answer
Any() stops as soon as it finds one element, so it is O(1) for most sources, and in EF Core it translates to an efficient SQL EXISTS. Count() may need to walk the entire sequence or run COUNT(*) on the table, which is wasteful just to check for existence. For List<T> or arrays, the Count or Length property is also fine because it is stored, but Any() expresses the intent clearly.
58

Sort a list of students by marks descending, then by name ascending.

Save to ▾
Show answer
var ranked = students .OrderByDescending(s => s.Marks) .ThenBy(s => s.Name) .ToList(); // in-place alternative with a comparison students.Sort((a, b) => b.Marks != a.Marks ? b.Marks.CompareTo(a.Marks) : string.Compare(a.Name, b.Name, StringComparison.Ordinal)); OrderBy is stable and returns a new sequence; List.Sort sorts in place and is not stable.
59

You need to remove inactive users from a List<User> while looping through it with foreach, and you get an InvalidOperationException. How do you fix it?

Save to ▾
Show answer
foreach does not allow modifying the collection it is enumerating, so the enumerator throws. The simplest fix is users.RemoveAll(u => !u.IsActive), which is efficient and clear. Alternatives are looping backwards with a for loop and RemoveAt, or building a new filtered list with Where and ToList. For a dictionary, collect keys to remove first, then remove them after the loop.
60

What is deferred execution in LINQ?

Save to ▾
Show answer
Most LINQ operators such as Where and Select do not run when you write them; they build a query that executes only when you enumerate it with foreach, ToList, Count or First. This means the query sees the latest data at enumeration time and can be composed step by step. The catch is that enumerating the same query twice runs it twice, which can mean two database calls. Call ToList to materialise once.
61

What is the difference between IEnumerable and IQueryable?

Save to ▾
Show answer
IEnumerable<T> works on in-memory data and executes LINQ with C# delegates, so filters run in the application. IQueryable<T> holds an expression tree that a provider such as EF Core translates into SQL, so filtering, sorting and paging happen in the database. If you return IEnumerable from a repository and then call Where, all rows may be loaded first. Keep queries as IQueryable until the final shape is ready.
62

What is the difference between Select and SelectMany?

Save to ▾
Show answer
Select projects each element to one result, so a list of customers mapped to their orders gives a list of lists. SelectMany projects each element to a sequence and flattens all sequences into one, so customers.SelectMany(c => c.Orders) gives a single list of all orders. In EF Core, SelectMany over a navigation collection translates to a SQL join, which is handy for reports.
63

Using LINQ, group employees by department and get the count and average salary.

Save to ▾
Show answer
var report = employees .GroupBy(e => e.Department) .Select(g => new { Department = g.Key, Count = g.Count(), AvgSalary = g.Average(e => e.Salary) }) .OrderByDescending(x => x.AvgSalary) .ToList(); GroupBy returns groups with a Key, and aggregate methods run per group. With EF Core this translates to SQL GROUP BY.
64

Write a LINQ query that joins orders with customers and returns customer name and order total.

Save to ▾
Show answer
var result = orders .Join(customers, o => o.CustomerId, c => c.Id, (o, c) => new { c.Name, o.Total }) .ToList(); // query syntax var result2 = (from o in orders join c in customers on o.CustomerId equals c.Id select new { c.Name, o.Total }).ToList(); Join is an inner join. For a left join use GroupJoin with DefaultIfEmpty, or the LeftJoin operator added in .NET 10.
65

What are generic constraints? Give examples.

Save to ▾
Show answer
Constraints restrict which types can be used for a type parameter so the generic code can rely on certain members. Examples: where T : class (reference type), where T : struct, where T : new() (has a parameterless constructor), where T : BaseEntity (inherits a class), where T : IComparable<T>, and where T : notnull. A repository might use where T : class, IEntity so it can read the Id property safely.
66

Show how yield return works with an example.

Save to ▾
Show answer
static IEnumerable<int> EvenNumbers(int max) { for (int i = 0; i <= max; i += 2) { yield return i; // pause here, resume on next MoveNext } } foreach (var n in EvenNumbers(10).Take(3)) Console.WriteLine(n); // 0 2 4 The compiler builds a state machine, so values are produced lazily one at a time. Only three values are generated here, which saves memory for large or infinite sequences.
67

Your code builds a LINQ query over a database, then calls Count() and later loops over it, and the logs show two SQL queries. Why, and how do you fix it?

Save to ▾
Show answer
This is multiple enumeration caused by deferred execution. The variable holds a query, not data, so Count runs one SQL statement and the foreach runs another. Besides extra load, the two results may differ if data changes in between. Materialise once with var list = await query.ToListAsync(), then use list.Count and loop over the list. Code analysers flag possible multiple enumeration of IEnumerable as a warning.
68

A job matches 2 lakh uploaded records against 2 lakh existing IDs using list.Where(x => existingIds.Contains(x.Id)) and takes minutes. What is wrong?

Save to ▾
Show answer
existingIds is a List, so Contains is O(n) and the whole operation becomes O(n x m), around 40 billion comparisons. Convert the IDs to a HashSet<int> first, making each lookup O(1) and the job run in milliseconds. If you also need associated data, build a Dictionary keyed by ID. Always check data structure complexity before parallelising or adding hardware.
69

Show the newer LINQ methods Chunk, DistinctBy and MaxBy.

Save to ▾
Show answer
// split 1,000 ids into batches of 100 for bulk API calls foreach (int[] batch in ids.Chunk(100)) await SendBatchAsync(batch); // unique customers by email var unique = customers.DistinctBy(c => c.Email).ToList(); // highest-paid employee object, not just the salary Employee? top = employees.MaxBy(e => e.Salary); These were added in .NET 6 and remove the need for custom helpers or third-party libraries like MoreLINQ.
70

Tell me about a time you improved the performance of slow code.

Save to ▾
Show answer
In my previous role (Situation) a daily reconciliation job took 40 minutes and sometimes missed its window. My task was to bring it under 10 minutes. I profiled it and found nested loops over two large lists and one database call per row. I replaced the inner loop with a Dictionary lookup and batched the database reads. Result: the job ran in about 4 minutes, and I documented the approach for the team.
71

How does Dictionary<TKey, TValue> work internally?

Save to ▾
Show answer
Dictionary is a hash table. It calls GetHashCode on the key to choose a bucket, then uses Equals to find the exact entry if several keys share a bucket. Lookups, inserts and deletes are O(1) on average. When it fills up, it resizes and rehashes. Keys must have stable hash codes, so never mutate a key object after inserting it, and override GetHashCode with Equals for custom key types.
72

Explain covariance and contravariance in C# generics.

Save to ▾
Show answer
Covariance, marked out T, lets you use a more derived type where a base type is expected: IEnumerable<string> can be assigned to IEnumerable<object> because the interface only returns T. Contravariance, marked in T, allows the reverse for inputs: an Action<object> can be used as Action<string>. They apply only to interfaces and delegates, and only with reference types. List<T> is invariant because it both reads and writes T.
73

Several threads update an in-memory Dictionary cache in a singleton service and you see corrupted data and exceptions. What would you use instead?

Save to ▾
Show answer
System.Collections.Concurrent provides thread-safe collections: ConcurrentDictionary, ConcurrentQueue, ConcurrentStack, ConcurrentBag and BlockingCollection. They use fine-grained locking or lock-free techniques, so multiple threads can read and write without your own lock. Use ConcurrentDictionary for in-memory caches in singleton services. Note that GetOrAdd may run the value factory more than once under contention, so keep the factory side-effect free or wrap it in Lazy<T>.
74

You load 5,000 pincode-to-city mappings at startup and read them millions of times a day from many threads. Which collection would you use?

Save to ▾
Show answer
Immutable collections like ImmutableList and ImmutableDictionary never change; modifications return a new collection that shares structure, which makes them safe to share across threads. FrozenDictionary and FrozenSet, added in .NET 8, are built once and heavily optimised for fast reads but cannot be modified. They suit lookup tables loaded at startup, such as state codes or feature flags, read millions of times per day.
75

An API endpoint calls _db.Orders.ToList().Where(o => o.CustomerId == id) and is slow as the table grows. Explain and fix it.

Save to ▾
Show answer
ToList executes immediately, so the entire Orders table is loaded into memory and then filtered in C#. As data grows, memory and response time grow with it. Move the filter before materialisation: await _db.Orders.Where(o => o.CustomerId == id).AsNoTracking().ToListAsync(). Now EF Core sends a WHERE clause, the database uses an index on CustomerId, and only matching rows travel over the network.
76

What do async and await do in C#?

Save to ▾
Show answer
async marks a method that can contain await, and the compiler turns it into a state machine. await pauses the method until a Task finishes without blocking the thread; the thread returns to the pool to do other work and the method resumes later, often on another thread. It is ideal for I/O such as database calls, HTTP requests and file reads. An async method returns Task, Task<T> or ValueTask.
77

A dashboard API calls three independent services one after another, each taking about 1 second. How can you make it faster?

Save to ▾
Show answer
Because the calls do not depend on each other, start all three tasks first without awaiting, then await Task.WhenAll. Total time becomes roughly the slowest call, about 1 second instead of 3. Add a timeout and handle failure of one service gracefully, for example showing partial data. If the same data is requested often, also add caching so most requests skip the calls entirely.
78

What is the difference between concurrency and parallelism?

Save to ▾
Show answer
Concurrency means dealing with many tasks at once by interleaving them, for example a web server handling thousands of requests that mostly wait on I/O. Parallelism means doing many computations at the same instant on multiple cores, such as processing an image in four chunks. async/await gives concurrency; Parallel.For and PLINQ give parallelism. A program can be concurrent on a single core but parallel only with multiple cores.
79

What is the difference between CPU-bound and I/O-bound work, and how do you handle each in .NET?

Save to ▾
Show answer
CPU-bound work keeps the processor busy, like encryption, image processing or heavy calculations; speed it up with parallelism using Parallel.For, PLINQ or Task.Run in desktop apps. I/O-bound work spends most time waiting on databases, files or networks; handle it with async/await so threads are released while waiting. Choosing wrongly wastes resources, such as using Parallel.ForEach for HTTP calls or Task.Run around database queries.
80

What is the difference between a Task and a Thread?

Save to ▾
Show answer
A Thread is an OS-level execution unit with its own stack, costly to create. A Task is a higher-level promise of work that may or may not use a thread; I/O tasks often use no thread while waiting, and CPU tasks run on pooled threads. Tasks support return values, continuations, cancellation, exceptions and composition with WhenAll. In modern .NET you almost always use Tasks rather than creating threads manually.
81

Why does using async in ASP.NET Core controllers improve scalability?

Save to ▾
Show answer
Each request needs a thread from the thread pool. If a controller blocks while waiting for SQL Server or an external API, that thread sits idle and cannot serve other users, so under load the pool runs out and requests queue. With async I/O, the thread is released during the wait and reused, so the same server handles many more concurrent requests. It does not make a single request faster.
82

Why should you avoid async void methods?

Save to ▾
Show answer
An async void method cannot be awaited, so the caller does not know when it finishes. Exceptions thrown inside it cannot be caught by the caller; they go to the synchronization context and can crash the process. It is also hard to unit test. Use async Task instead. The only accepted use of async void is for event handlers, such as button click handlers in desktop apps, where the signature is fixed.
83

Show how Task.WhenAll and Task.WhenAny are used.

Save to ▾
Show answer
// run three independent calls in parallel var userTask = userApi.GetAsync(id); var ordersTask = orderApi.GetAsync(id); var walletTask = walletApi.GetAsync(id); await Task.WhenAll(userTask, ordersTask, walletTask); var dashboard = new Dashboard(userTask.Result, ordersTask.Result, walletTask.Result); // timeout using WhenAny var work = SlowCallAsync(); if (await Task.WhenAny(work, Task.Delay(2000)) != work) throw new TimeoutException(); WhenAll completes when all finish; WhenAny returns the first task to finish.
84

How do you use CancellationToken in an ASP.NET Core API?

Save to ▾
Show answer
[HttpGet("report")] public async Task<IActionResult> Report(CancellationToken ct) { var rows = await _db.Sales .Where(s => s.Year == 2026) .ToListAsync(ct); await _http.PostAsJsonAsync("/audit", rows.Count, ct); return Ok(rows); } ASP.NET Core binds the token to HttpContext.RequestAborted, so if the user closes the browser the token is cancelled and EF Core and HttpClient stop work, saving database and CPU time.
85

What does the lock keyword do?

Save to ▾
Show answer
lock ensures that only one thread at a time executes a block of code for a given lock object, preventing race conditions on shared data. It compiles to Monitor.Enter and Monitor.Exit inside try-finally. Lock on a private readonly object, never on this or a string. Since .NET 9 there is a dedicated System.Threading.Lock type that is faster. You cannot await inside a lock; use SemaphoreSlim for async code.
86

Demonstrate a race condition on a counter and fix it.

Save to ▾
Show answer
int count = 0; Parallel.For(0, 100_000, _ => count++); Console.WriteLine(count); // often less than 100000 int safe = 0; Parallel.For(0, 100_000, _ => Interlocked.Increment(ref safe)); Console.WriteLine(safe); // always 100000 count++ is a read, add and write, so two threads can read the same value and lose an update. Interlocked performs the increment atomically without a full lock.
87

You must resize 10,000 images and also call an external API for 10,000 records. Which approach do you use for each task?

Save to ▾
Show answer
Parallel.ForEach is for CPU-bound work, such as resizing thousands of images, where splitting work across cores speeds things up. async/await is for I/O-bound work, where you mostly wait on networks or disks. Using Parallel.ForEach for HTTP calls wastes threads while they wait. For many concurrent I/O operations with a limit, use Parallel.ForEachAsync with MaxDegreeOfParallelism, available since .NET 6.
88

Show how to stream data with IAsyncEnumerable.

Save to ▾
Show answer
public async IAsyncEnumerable<Order> GetOrdersAsync( [EnumeratorCancellation] CancellationToken ct = default) { await foreach (var o in _db.Orders.AsNoTracking().AsAsyncEnumerable().WithCancellation(ct)) yield return o; } // consumer await foreach (var order in service.GetOrdersAsync()) Console.WriteLine(order.Id); Items are produced and consumed one at a time asynchronously. ASP.NET Core can stream an IAsyncEnumerable result as JSON without buffering the whole list.
89

Write a BackgroundService that cleans expired OTPs every 5 minutes.

Save to ▾
Show answer
public class OtpCleanupService(IServiceScopeFactory scopes) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken ct) { using var timer = new PeriodicTimer(TimeSpan.FromMinutes(5)); while (await timer.WaitForNextTickAsync(ct)) { using var scope = scopes.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); await db.Otps.Where(o => o.ExpiresAt < DateTime.UtcNow).ExecuteDeleteAsync(ct); } } } // builder.Services.AddHostedService<OtpCleanupService>(); A scope is created because DbContext is scoped while hosted services are singletons.
90

A developer wraps every database call in Task.Run inside ASP.NET Core controllers to make them async. Is this a good idea?

Save to ▾
Show answer
No. Task.Run moves work to another thread pool thread, but the request still waits for it, so you use two threads instead of one and gain nothing. The database call itself is still blocking. The correct approach is to use true async APIs like ToListAsync and SaveChangesAsync, which release the thread during I/O. Task.Run makes sense mainly in desktop apps to keep the UI thread free.
91

Users trigger a large Excel report that takes 3 minutes, and the HTTP request times out. How would you redesign it?

Save to ▾
Show answer
Make it asynchronous at the workflow level. The API validates the request, saves a job record and returns 202 Accepted with a job ID. A background worker, using a queue such as a Channel, Hangfire or a message broker, generates the file and stores it in blob storage. The UI polls a status endpoint or receives a SignalR notification, then downloads the file. This avoids timeouts and survives retries.
92

Tell me about a production bug you had to debug under time pressure.

Save to ▾
Show answer
Last year (Situation) our order API started timing out during a sale. My task was to restore service fast. I checked dashboards, saw thread count climbing with low CPU, and took a dump that showed threads blocked on a .Result call added in a recent release. Action: I hotfixed it to proper async and rolled out within an hour. Result: latency returned to normal, and I added an analyser rule to block sync-over-async.
93

A legacy ASP.NET MVC app on .NET Framework hangs when a controller calls GetDataAsync().Result. Why, and how do you fix it?

Save to ▾
Show answer
This is the classic sync-over-async deadlock. .Result blocks the request thread, which holds the ASP.NET synchronization context. When the awaited task completes, its continuation tries to resume on that same context, which is blocked, so neither can proceed. The real fix is async all the way: make the action async and await the call. Where that is impossible, ConfigureAwait(false) inside the library avoids capturing the context.
94

What does ConfigureAwait(false) do and is it needed in ASP.NET Core?

Save to ▾
Show answer
By default await captures the current SynchronizationContext and resumes on it. ConfigureAwait(false) tells the runtime it can resume on any thread pool thread, which avoids deadlocks in UI and old ASP.NET apps and slightly reduces overhead. ASP.NET Core has no SynchronizationContext, so it is not required in application code there. It is still recommended in general-purpose libraries that might be used by WPF or WinForms apps.
95

Profiling shows a hot cache-lookup method returning Task<T> allocates millions of Task objects. Would ValueTask help?

Save to ▾
Show answer
ValueTask<T> is a struct that avoids allocating a Task when a method usually completes synchronously, for example when a value is served from an in-memory cache most of the time. In very hot paths this reduces GC pressure. The rules are stricter: await a ValueTask only once, do not await it concurrently, and do not call .Result before it completes. For normal application code, Task is simpler and recommended.
96

Limit concurrent calls to a third-party API to 5 at a time using SemaphoreSlim.

Save to ▾
Show answer
private static readonly SemaphoreSlim _gate = new(5); public async Task<string> CallAsync(string url) { await _gate.WaitAsync(); try { return await _http.GetStringAsync(url); } finally { _gate.Release(); } } var results = await Task.WhenAll(urls.Select(CallAsync)); SemaphoreSlim supports async waiting, unlike lock. The finally block guarantees the slot is released even when a call fails.
97

Under load, an API's response time jumps to many seconds while CPU stays low. Thread count keeps rising. What is likely happening?

Save to ▾
Show answer
This pattern points to thread pool starvation. Some code is blocking threads with .Result, .Wait(), Thread.Sleep or synchronous I/O, so pool threads are stuck waiting and the pool injects new threads slowly. Confirm with dotnet-counters, watching thread pool queue length and thread count, and a dump showing many threads blocked in Wait. Fix by making the call chain fully async; raising minimum threads is only a temporary patch.
98

What are System.Threading.Channels and when would you use them?

Save to ▾
Show answer
Channels provide fast, thread-safe, async producer-consumer queues. A producer writes with await writer.WriteAsync and a consumer reads with await foreach over reader.ReadAllAsync. Bounded channels apply back-pressure by making producers wait when full. They are useful inside one process, for example an API that accepts uploads quickly and hands them to a background worker. For durable or cross-service queues use a broker like RabbitMQ or Azure Service Bus.
99

How are exceptions handled in async code, and what is AggregateException?

Save to ▾
Show answer
When you await a faulted task, the original exception is rethrown, so normal try-catch works. If you block with .Wait() or .Result, the exception is wrapped in AggregateException. With Task.WhenAll, await throws only the first exception, but the returned task's Exception property holds all of them in an AggregateException. Unobserved exceptions from fire-and-forget tasks are silently lost, so always await or log them.
100

What is a SynchronizationContext?

Save to ▾
Show answer
A SynchronizationContext represents where continuations should run. WPF and WinForms have one that marshals work back to the UI thread, so after await you can update controls safely. Classic ASP.NET had one tied to the request. ASP.NET Core and console apps have none, so continuations run on any thread pool thread. Understanding it explains why .Result deadlocks in UI apps but often not in ASP.NET Core.
101

What is ASP.NET Core and what are its main features?

Save to ▾
Show answer
ASP.NET Core is the open-source, cross-platform framework for building web APIs, MVC sites, Razor Pages, Blazor apps and real-time apps with SignalR on modern .NET. Key features are built-in dependency injection, a configurable middleware pipeline, the fast Kestrel web server, unified configuration and logging, and support for Docker and cloud hosting. It runs on Windows, Linux and macOS and consistently ranks among the fastest web frameworks.
102

What is the middleware pipeline in ASP.NET Core?

Save to ▾
Show answer
Every HTTP request passes through a chain of middleware components configured in Program.cs. Each component can inspect or modify the request, call the next one, and then work on the response on the way back. Order matters: exception handling first, then HTTPS redirection, static files, routing, CORS, authentication, authorization and finally endpoints. For example, putting UseAuthorization before UseAuthentication means users never appear logged in.
103

Explain the transient, scoped and singleton service lifetimes.

Save to ▾
Show answer
Transient services are created every time they are requested, suitable for lightweight stateless helpers. Scoped services are created once per HTTP request and shared within it; DbContext is registered as scoped. Singleton services are created once for the whole application lifetime, suitable for caches and configuration. Choose based on state: anything holding per-request data must not be singleton, and singletons must be thread-safe.
104

Show attribute routing for a products controller with route constraints.

Save to ▾
Show answer
[ApiController] [Route("api/[controller]")] public class ProductsController(IProductService service) : ControllerBase { [HttpGet] public async Task<IActionResult> GetAll() => Ok(await service.GetAllAsync()); [HttpGet("{id:int}")] public async Task<IActionResult> Get(int id) { var p = await service.GetAsync(id); return p is null ? NotFound() : Ok(p); } [HttpPost] public async Task<IActionResult> Create(ProductDto dto) { var created = await service.CreateAsync(dto); return CreatedAtAction(nameof(Get), new { id = created.Id }, created); } }
105

What is the difference between authentication and authorization in ASP.NET Core?

Save to ▾
Show answer
Authentication answers who you are: middleware reads a cookie or JWT, validates it and builds a ClaimsPrincipal for HttpContext.User. Authorization answers what you may do: it checks that user against rules such as [Authorize(Roles = "Admin")] or a policy like requiring an Employee claim with a certain department. A missing or invalid identity gives 401 Unauthorized, while a valid user without permission gets 403 Forbidden.
106

What is CORS and how do you enable it in ASP.NET Core?

Save to ▾
Show answer
Browsers block JavaScript from calling an API on a different origin (scheme, host or port) unless the server allows it via CORS headers. If an Angular app on localhost:4200 calls an API on localhost:5001, you add a policy with builder.Services.AddCors, allowing that origin with WithOrigins, plus required methods and headers, and call app.UseCors before authorization. Avoid AllowAnyOrigin in production, especially with credentials.
107

Which HTTP status codes and methods should a REST API use, and what is the difference between PUT and PATCH?

Save to ▾
Show answer
GET reads, POST creates, PUT replaces, PATCH partially updates and DELETE removes. Return 200 OK for success with a body, 201 Created with a Location header after POST, 204 No Content after delete, 400 for invalid input, 401 unauthenticated, 403 forbidden, 404 not found, 409 conflict and 500 for server errors. PUT sends the full resource and is idempotent; PATCH sends only changed fields.
108

Write custom middleware that logs how long each request takes.

Save to ▾
Show answer
public class TimingMiddleware(RequestDelegate next, ILogger<TimingMiddleware> logger) { public async Task InvokeAsync(HttpContext context) { var sw = Stopwatch.StartNew(); await next(context); sw.Stop(); logger.LogInformation("{Method} {Path} -> {Status} in {Ms} ms", context.Request.Method, context.Request.Path, context.Response.StatusCode, sw.ElapsedMilliseconds); } } // Program.cs app.UseMiddleware<TimingMiddleware>(); Code before next runs on the request, code after it runs on the response.
109

What is the difference between controllers and Minimal APIs?

Save to ▾
Show answer
Controllers group actions into classes with attributes for routing, filters and model binding, which suits large APIs with many conventions. Minimal APIs map endpoints directly with app.MapGet and lambdas, with less ceremony and slightly better performance, ideal for microservices and small APIs. Since .NET 7 they support filters, route groups and OpenAPI, and .NET 10 adds built-in validation, so both are production-ready choices.
110

How do model binding and validation work in ASP.NET Core Web API?

Save to ▾
Show answer
Model binding maps request data into action parameters from the route, query string, headers or body, using [FromRoute], [FromQuery] and [FromBody]. Validation uses data annotations like [Required], [StringLength] and [Range] on DTOs. With [ApiController], invalid models automatically return 400 Bad Request with ProblemDetails listing the errors, so you do not need to check ModelState manually. FluentValidation is popular for complex rules.
111

What types of filters exist in ASP.NET Core MVC?

Save to ▾
Show answer
Authorization filters run first and can block a request. Resource filters run before model binding, useful for caching. Action filters run before and after an action, for logging or validation. Exception filters handle errors thrown by actions. Result filters run around the result execution, for example to add headers. Filters apply globally, per controller or per action. Unlike middleware, they can access MVC details like action arguments.
112

Implement global exception handling that returns ProblemDetails.

Save to ▾
Show answer
public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler { public async ValueTask<bool> TryHandleAsync(HttpContext ctx, Exception ex, CancellationToken ct) { logger.LogError(ex, "Unhandled error"); var status = ex is KeyNotFoundException ? 404 : 500; ctx.Response.StatusCode = status; await ctx.Response.WriteAsJsonAsync(new ProblemDetails { Status = status, Title = status == 404 ? "Not found" : "Server error" }, ct); return true; } } // Program.cs builder.Services.AddExceptionHandler<GlobalExceptionHandler>(); builder.Services.AddProblemDetails(); app.UseExceptionHandler();
113

Configure JWT bearer authentication in an ASP.NET Core API.

Save to ▾
Show answer
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)) }; }); builder.Services.AddAuthorization(); app.UseAuthentication(); app.UseAuthorization(); Then protect endpoints with [Authorize] or [Authorize(Roles = "Admin")].
114

Show how to bind configuration from appsettings.json using the Options pattern.

Save to ▾
Show answer
// appsettings.json // "Smtp": { "Host": "smtp.example.com", "Port": 587 } public class SmtpOptions { public string Host { get; set; } = ""; public int Port { get; set; } } builder.Services.Configure<SmtpOptions>(builder.Configuration.GetSection("Smtp")); public class EmailService(IOptions<SmtpOptions> options) { private readonly SmtpOptions _smtp = options.Value; } appsettings.{Environment}.json and environment variables override base values. Use IOptionsMonitor to pick up changes without restart.
115

How does logging work in ASP.NET Core?

Save to ▾
Show answer
ASP.NET Core has a built-in ILogger<T> abstraction injected into any class. You log with levels Trace, Debug, Information, Warning, Error and Critical, and configure minimum levels per category in appsettings.json. Use structured logging with message templates, like logger.LogInformation("Order {OrderId} placed", id), so values become searchable fields. Providers such as Serilog or OpenTelemetry send logs to files, Seq, Elasticsearch or Application Insights.
116

An API creates a new HttpClient inside a using block for every outgoing call, and under load you see socket exhaustion errors. How do you fix it?

Save to ▾
Show answer
Disposing HttpClient does not immediately free the underlying socket; connections stay in TIME_WAIT, so thousands of short-lived clients exhaust ports. A single static client fixes that but misses DNS changes. The recommended fix is IHttpClientFactory: register builder.Services.AddHttpClient<PaymentClient>() and inject the typed client. The factory pools and rotates handlers, and you can add resilience with Microsoft.Extensions.Http.Resilience for retries and timeouts.
117

You must change an API response format, but an older mobile app version still calls it. How do you avoid breaking those users?

Save to ▾
Show answer
Versioning lets you change contracts without breaking existing clients such as mobile apps that users have not updated. Common approaches are URL segments (/api/v1/orders), query strings (?api-version=2.0) and headers. The Asp.Versioning library supports all of them and integrates with OpenAPI docs. URL versioning is the most visible and cache-friendly. Keep old versions running for a published period, then deprecate them with headers.
118

Describe an API you designed end to end and the decisions you made.

Save to ▾
Show answer
In my last project (Situation) we needed a leave-management API for 3,000 employees. My task was the full design. I modelled resources like /employees/{id}/leaves, used DTOs separate from EF entities, JWT with role policies for managers, FluentValidation, ProblemDetails errors and paging on every list. I documented it in OpenAPI and agreed the contract with the Angular team first. Result: front and back ends were built in parallel and launched on time.
119

Where should you store secrets like connection strings and API keys in an ASP.NET Core app?

Save to ▾
Show answer
Never commit them in appsettings.json. During development use the Secret Manager (dotnet user-secrets), which stores them outside the project folder. In production use environment variables or, better, a vault such as Azure Key Vault or AWS Secrets Manager, loaded through a configuration provider and accessed with managed identity so no credential sits in code. Rotate secrets regularly and restrict who can read them.
120

Tell me about a disagreement with the front-end team over an API contract and how you resolved it.

Save to ▾
Show answer
On a dashboard feature (Situation) the React team wanted one endpoint returning everything, while I worried about payload size. My task was to agree a design quickly. I set up a short call, we listed exact screen needs, and I proposed one aggregated endpoint with paging and optional fields. We wrote the OpenAPI spec together. Result: payload dropped by half, the UI got one call, and the spec became our template for later features.
121

A singleton CacheService injects AppDbContext, and users start seeing stale data and occasional 'a second operation was started on this context' errors. What is wrong?

Save to ▾
Show answer
This is a captive dependency: a scoped DbContext is captured by a singleton, so one context lives forever and is shared by all requests across threads. DbContext is not thread-safe and its change tracker grows stale. Fix it by injecting IServiceScopeFactory or IDbContextFactory<AppDbContext> into the singleton and creating a short-lived context per operation. Enabling ValidateScopes in development catches this at startup.
122

Your product API runs on four instances behind a load balancer and needs caching. Which ASP.NET Core caching options would you consider?

Save to ▾
Show answer
IMemoryCache stores data in the server's memory, fast but not shared across instances. IDistributedCache uses Redis or SQL Server so all instances share the cache. HybridCache, added in .NET 9, combines an in-memory layer with a distributed one and prevents cache stampedes. Output caching stores whole HTTP responses on the server, while response caching sets HTTP headers for browsers and proxies. Always set expiry and invalidate when data changes.
123

Add rate limiting to a login endpoint in ASP.NET Core.

Save to ▾
Show answer
builder.Services.AddRateLimiter(o => { o.RejectionStatusCode = StatusCodes.Status429TooManyRequests; o.AddPolicy("login", ctx => RateLimitPartition.GetFixedWindowLimiter( ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown", _ => new FixedWindowRateLimiterOptions { PermitLimit = 5, Window = TimeSpan.FromMinutes(1) })); }); app.UseRateLimiter(); app.MapPost("/api/login", LoginHandler).RequireRateLimiting("login"); Each IP gets 5 attempts per minute, which slows brute-force attacks. Behind a proxy, use the forwarded client IP.
124

Your product API must handle a festive sale with 10 times normal traffic. How do you prepare it?

Save to ▾
Show answer
Make the API stateless so you can scale it horizontally behind a load balancer or Kubernetes autoscaler. Cache read-heavy data such as product details in Redis or HybridCache. Ensure all I/O is async and database queries are indexed, projected and paged. Move slow work like emails to queues. Add rate limiting, timeouts and circuit breakers to dependencies, then load test with k6 or JMeter and watch metrics.
125

Access tokens in your app expire in 15 minutes and users complain about being logged out. How do you implement refresh tokens securely?

Save to ▾
Show answer
Issue a short-lived JWT access token plus a long-lived, random refresh token stored hashed in the database with expiry and device info. When the access token expires, the client calls /refresh with the refresh token; the server validates it, revokes it and issues a new pair, which is rotation. Reuse of a revoked token signals theft, so revoke the whole chain. In browsers, store the refresh token in an HttpOnly, Secure, SameSite cookie.
126

What is Entity Framework Core?

Save to ▾
Show answer
EF Core is Microsoft's object-relational mapper for .NET. It maps C# classes to database tables, translates LINQ queries into SQL, tracks changes to loaded objects and saves them with SaveChanges. It supports SQL Server, PostgreSQL, MySQL, SQLite, Cosmos DB and more through providers. It removes most hand-written data access code, while still allowing raw SQL when needed. EF Core 10 ships with .NET 10.
127

What is the difference between code-first and database-first approaches?

Save to ▾
Show answer
In code-first, you write entity classes and a DbContext, and EF Core migrations create and evolve the database schema from code; it suits new projects and keeps schema in source control. In database-first, the database already exists and you scaffold entities with dotnet ef dbcontext scaffold. It suits legacy databases managed by a DBA team. Many teams scaffold once and then continue code-first.
128

What are DbContext and DbSet, and what lifetime should DbContext have?

Save to ▾
Show answer
DbContext represents a session with the database: it holds configuration, the change tracker and connection handling. Each DbSet<T> property represents a table you can query and add to. DbContext is lightweight and not thread-safe, so it should be short-lived; in ASP.NET Core it is registered as scoped, one per request, via AddDbContext. For background services or Blazor, use IDbContextFactory to create contexts on demand.
129

Which commands do you use to create and apply EF Core migrations?

Save to ▾
Show answer
dotnet tool install --global dotnet-ef # create a migration from model changes dotnet ef migrations add AddOrderStatus # apply pending migrations to the database dotnet ef database update # undo the last unapplied migration dotnet ef migrations remove # generate an idempotent SQL script for production dotnet ef migrations script --idempotent -o deploy.sql In Visual Studio the Package Manager Console equivalents are Add-Migration and Update-Database.
130

How do you keep up with new .NET and EF Core releases?

Save to ▾
Show answer
Microsoft ships a major .NET version every November, so I plan for it. I read the official What's New pages and the .NET blog, watch .NET Conf sessions, and try new features in a small side project before suggesting them at work. For example, when ExecuteUpdate arrived, I tested it on a sample and then proposed replacing a slow loop in our cleanup job, which cut its runtime significantly.
131

Explain eager, lazy and explicit loading in EF Core.

Save to ▾
Show answer
Eager loading fetches related data in the same query using Include and ThenInclude, for example orders with their items. Lazy loading loads a navigation property automatically the first time you access it, requiring proxies and virtual properties; it is convenient but easily causes N+1 queries. Explicit loading loads a navigation on demand with Entry(order).Collection(o => o.Items).LoadAsync(). Projection with Select is often better than all three.
132

A page listing 100 orders with customer names runs 101 SQL queries. What is the problem and how do you fix it?

Save to ▾
Show answer
This is the N+1 problem: one query loads the orders, then lazy loading fires a separate query for each order's Customer. Fix it by loading everything in one query, either with Include(o => o.Customer) or better with a projection: Select(o => new OrderListDto(o.Id, o.Total, o.Customer.Name)), which fetches only needed columns via a join. Turn on EF Core logging to spot such patterns early.
133

A read-only product listing endpoint in EF Core uses a lot of memory and CPU. What simple change helps, and why?

Save to ▾
Show answer
By default, EF Core tracks every entity it loads so it can detect changes on SaveChanges, which costs memory and CPU. AsNoTracking tells EF Core not to track the results, making read-only queries faster and lighter. Use it for lists, reports and GET endpoints where you will not update the data. AsNoTrackingWithIdentityResolution avoids duplicate instances of the same entity in results while still skipping tracking.
134

Configure a one-to-many relationship between Customer and Order using the Fluent API.

Save to ▾
Show answer
public class Customer { public int Id { get; set; } public List<Order> Orders { get; set; } = []; } public class Order { public int Id { get; set; } public int CustomerId { get; set; } public Customer Customer { get; set; } = null!; } protected override void OnModelCreating(ModelBuilder mb) { mb.Entity<Order>() .HasOne(o => o.Customer) .WithMany(c => c.Orders) .HasForeignKey(o => o.CustomerId) .OnDelete(DeleteBehavior.Restrict); mb.Entity<Order>().Property(o => o.Total).HasPrecision(18, 2); } Restrict prevents deleting a customer who still has orders.
135

How does EF Core handle many-to-many relationships?

Save to ▾
Show answer
Since EF Core 5, you can define collection navigations on both sides, such as Student.Courses and Course.Students, and EF Core creates a hidden join table automatically. If the join needs extra data, like EnrolledOn or Grade, create an explicit join entity Enrollment with two foreign keys and configure it with UsingEntity or two one-to-many relationships. Querying works naturally with Include or projections through the navigations.
136

How do you run raw SQL safely in EF Core?

Save to ▾
Show answer
// entity query with parameters (interpolation becomes SqlParameter) var orders = await db.Orders .FromSql($"SELECT * FROM Orders WHERE City = {city}") .Where(o => o.Total > 1000) .ToListAsync(); // non-entity results var totals = await db.Database .SqlQuery<decimal>($"SELECT SUM(Total) AS Value FROM Orders") .ToListAsync(); // stored procedure await db.Database.ExecuteSqlAsync($"EXEC usp_CloseMonth {month}"); Never build SQL by string concatenation; FromSqlRaw with concatenated input invites SQL injection.
137

Show bulk update and delete with ExecuteUpdate and ExecuteDelete.

Save to ▾
Show answer
// mark all unpaid invoices older than 30 days as overdue int updated = await db.Invoices .Where(i => !i.IsPaid && i.DueDate < DateTime.UtcNow.AddDays(-30)) .ExecuteUpdateAsync(s => s .SetProperty(i => i.Status, "Overdue") .SetProperty(i => i.UpdatedAt, DateTime.UtcNow)); // delete old logs int deleted = await db.AuditLogs .Where(l => l.CreatedAt < cutoff) .ExecuteDeleteAsync(); These run a single SQL UPDATE or DELETE without loading entities, available since EF Core 7. They bypass the change tracker.
138

How do you use an explicit transaction in EF Core across multiple SaveChanges calls?

Save to ▾
Show answer
await using var tx = await db.Database.BeginTransactionAsync(); try { db.Orders.Add(order); await db.SaveChangesAsync(); var stock = await db.Stocks.SingleAsync(s => s.ProductId == order.ProductId); stock.Quantity -= order.Quantity; await db.SaveChangesAsync(); await tx.CommitAsync(); } catch { await tx.RollbackAsync(); throw; } A single SaveChanges is already transactional; explicit transactions are needed when you combine several saves or raw SQL into one unit.
139

A developer runs two EF Core queries in parallel with Task.WhenAll on the same DbContext and gets an InvalidOperationException. Why?

Save to ▾
Show answer
DbContext is not thread-safe and supports only one active operation at a time, so starting a second query before the first finishes throws 'A second operation was started on this context instance'. Either await the queries one after another, or create a separate context for each parallel query using IDbContextFactory. Usually sequential queries are fine; parallelism only helps when the queries are slow and independent.
140

Explain a technical trade-off you had to justify to a manager or client.

Save to ▾
Show answer
On a reporting module (Situation) the manager wanted everything in EF Core for consistency, but one report was too slow. My task was to recommend a fix without derailing the plan. I measured the EF query against a Dapper version with a hand-tuned SQL query, showed the 8x difference and explained that we would use Dapper only for that read path. Result: the manager approved, the report loaded in under a second, and the rest stayed in EF Core.
141

Implement paging for a product list in EF Core.

Save to ▾
Show answer
public async Task<PagedResult<ProductDto>> GetPageAsync(int page, int size) { var query = db.Products.AsNoTracking().OrderBy(p => p.Id); int total = await query.CountAsync(); var items = await query .Skip((page - 1) * size) .Take(size) .Select(p => new ProductDto(p.Id, p.Name, p.Price)) .ToListAsync(); return new PagedResult<ProductDto>(items, total, page, size); } Always order before Skip and Take. For very deep pages, keyset paging with Where(p => p.Id > lastId) is faster than large offsets.
142

How does change tracking work and what are entity states?

Save to ▾
Show answer
The change tracker keeps a snapshot of each tracked entity and compares it on SaveChanges. Each entity has a state: Added (insert), Modified (update), Deleted (delete), Unchanged (no action) and Detached (not tracked). Calling Add, Update or Remove sets states, and changing a property of a tracked entity marks it Modified. SaveChanges then generates SQL only for changed columns, all inside one transaction.
143

Two support agents edit the same customer record at once and one agent's changes silently overwrite the other's. How do you prevent this?

Save to ▾
Show answer
Use optimistic concurrency. Add a [Timestamp] byte[] RowVersion property, which maps to SQL Server rowversion. EF Core includes it in the WHERE clause of updates; if another user changed the row, zero rows are affected and DbUpdateConcurrencyException is thrown. Catch it, reload current values and show the agent a conflict message or merge screen. This avoids locking rows while users are editing on screen.
144

Implement soft delete with a global query filter.

Save to ▾
Show answer
public class Product { public int Id { get; set; } public bool IsDeleted { get; set; } } protected override void OnModelCreating(ModelBuilder mb) { mb.Entity<Product>().HasQueryFilter(p => !p.IsDeleted); } public override Task<int> SaveChangesAsync(CancellationToken ct = default) { foreach (var e in ChangeTracker.Entries<Product>().Where(e => e.State == EntityState.Deleted)) { e.State = EntityState.Modified; e.Entity.IsDeleted = true; } return base.SaveChangesAsync(ct); } Every query now hides deleted rows automatically; use IgnoreQueryFilters() for admin screens.
145

What techniques improve EF Core query performance?

Save to ▾
Show answer
Project only needed columns with Select instead of loading full entities. Use AsNoTracking for reads. Avoid N+1 with Include or projections. Page with Skip and Take or keyset paging. Add proper indexes via HasIndex. Use ExecuteUpdate and ExecuteDelete for bulk changes. For hot queries, compiled queries with EF.CompileAsyncQuery and DbContext pooling with AddDbContextPool reduce overhead. Always check generated SQL with logging or ToQueryString.
146

An EF Core query that includes Items and Payments for each order returns a huge, duplicated result set. What is happening and how do split queries help?

Save to ▾
Show answer
When you Include two or more collection navigations, such as Orders with Items and Payments, EF Core generates one query with joins. Rows multiply: 10 items times 5 payments return 50 rows per order, duplicating data heavily. AsSplitQuery() tells EF Core to run separate queries per collection and stitch results together, avoiding duplication. The trade-off is more round trips and possible inconsistency without a transaction.
147

Your team debates wrapping EF Core in a generic repository. What is your view?

Save to ▾
Show answer
DbContext already implements Repository and Unit of Work, so a thin generic repository with GetAll and Add often adds code while hiding useful features like Include, projections and AsNoTracking. I prefer either using DbContext directly in services, or specific repositories with meaningful methods like GetOverdueInvoicesAsync that encapsulate queries. For tests, use the SQLite in-memory provider or Testcontainers rather than mocking DbSet.
148

A complex reporting query written in EF Core is slow and hard to tune. When would you move it to Dapper?

Save to ▾
Show answer
Dapper is a micro-ORM that maps raw SQL results to objects with very low overhead. It suits read-heavy reports, complex hand-tuned queries and stored procedures where you want full SQL control. EF Core offers change tracking, migrations, LINQ and relationships, which speed up CRUD development. Many projects use both: EF Core for writes and normal features, Dapper for performance-critical queries, sharing the same connection string.
149

You must rename a column and split a Name field into FirstName and LastName in a production database with live data. How do you deploy safely?

Save to ▾
Show answer
Avoid destructive one-step migrations. Use an expand-and-contract approach: first add new nullable columns, deploy code that writes both old and new, and backfill data with a script in batches. Then switch reads to the new columns, and only in a later release drop the old column. Generate idempotent SQL scripts, review them with the DBA, take a backup and test on a production copy first.
150

Your multi-tenant SaaS app keeps all tenants in one database. How do you make sure EF Core queries never return another tenant's data?

Save to ▾
Show answer
Add a TenantId column to every tenant-owned entity and a global query filter such as HasQueryFilter(e => e.TenantId == _tenantId), where the tenant ID comes from a scoped provider that reads the authenticated user's claim. Set TenantId automatically in SaveChanges for new rows. Index TenantId, write integration tests that try cross-tenant access, audit every IgnoreQueryFilters call, and consider SQL Server row-level security as a second layer of defence.
151

What is the difference between a primary key and a unique key in SQL Server?

Save to ▾
Show answer
Both enforce uniqueness. A table can have only one primary key, it cannot contain NULLs, and by default SQL Server creates a clustered index for it. A table can have many unique constraints, each allowing a single NULL in SQL Server, and they create non-clustered indexes by default. Use the primary key for row identity, such as EmployeeId, and unique keys for business rules like a unique email or PAN.
152

Explain the different types of SQL joins.

Save to ▾
Show answer
INNER JOIN returns rows that match in both tables. LEFT JOIN returns all rows from the left table plus matches from the right, with NULLs where there is no match. RIGHT JOIN is the mirror. FULL OUTER JOIN returns all rows from both sides. CROSS JOIN returns every combination. A self join joins a table to itself, such as employees to their managers. LEFT JOIN with WHERE right.Id IS NULL finds unmatched rows.
153

Write a SQL Server query to find the second highest salary.

Save to ▾
Show answer
-- using DENSE_RANK (handles ties) SELECT Salary FROM ( SELECT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) AS rnk FROM Employees ) t WHERE rnk = 2; -- using OFFSET SELECT DISTINCT Salary FROM Employees ORDER BY Salary DESC OFFSET 1 ROW FETCH NEXT 1 ROW ONLY; Change 2 to N for the Nth highest salary.
154

Write a query to find duplicate email addresses and delete the extra rows, keeping the lowest Id.

Save to ▾
Show answer
-- find duplicates SELECT Email, COUNT(*) AS Cnt FROM Users GROUP BY Email HAVING COUNT(*) > 1; -- delete duplicates, keep lowest Id WITH d AS ( SELECT Id, ROW_NUMBER() OVER (PARTITION BY Email ORDER BY Id) AS rn FROM Users ) DELETE FROM d WHERE rn > 1; After cleanup, add a unique index on Email to stop duplicates returning.
155

What is the difference between WHERE and HAVING?

Save to ▾
Show answer
WHERE filters individual rows before grouping and cannot use aggregate functions. HAVING filters groups after GROUP BY and can use aggregates like COUNT or SUM. For example, WHERE City = 'Pune' keeps only Pune rows, then GROUP BY DepartmentId HAVING COUNT(*) > 10 keeps departments with more than 10 such employees. Put non-aggregate conditions in WHERE so fewer rows are grouped, which is faster.
156

What is the difference between DELETE, TRUNCATE and DROP?

Save to ▾
Show answer
DELETE removes rows one by one, supports WHERE, fires triggers and is fully logged, so it is slower on big tables. TRUNCATE removes all rows by deallocating pages, is minimally logged, resets identity values and cannot have WHERE; it fails if foreign keys reference the table. DROP removes the whole table including structure, indexes and permissions. In SQL Server, both DELETE and TRUNCATE can be rolled back inside a transaction.
157

Explain normalisation and the first three normal forms.

Save to ▾
Show answer
Normalisation organises tables to reduce redundancy and update anomalies. 1NF: each column holds atomic values and there are no repeating groups. 2NF: in 1NF and every non-key column depends on the whole primary key, not part of a composite key. 3NF: in 2NF and non-key columns do not depend on other non-key columns, for example City should not be stored with an order if it depends on the customer. Reporting databases may denormalise for speed.
158

What is SQL injection and how do you prevent it in a .NET application?

Save to ▾
Show answer
SQL injection happens when user input is concatenated into SQL text, letting attackers change the query, for example entering ' OR 1=1 -- in a login box. Prevent it by always using parameters: SqlCommand with SqlParameter, EF Core LINQ, FromSql with interpolation, or Dapper parameters. Also use least-privilege database accounts, validate input and never show raw database errors to users. Stored procedures help only if they also avoid dynamic SQL concatenation.
159

What are your strengths and weaknesses as a developer?

Save to ▾
Show answer
My strength is that I go deep when debugging; I like reading execution plans and logs until I find the real cause, which has helped my team fix slow queries. A weakness was that I spent too long polishing code before asking for feedback. I now open small draft pull requests early and ask for review, which has made me faster and helped me learn from seniors sooner.
160

Where do you see yourself in five years?

Save to ▾
Show answer
In five years I want to be a senior full stack engineer who can design a complete .NET system, from database and APIs to front end and cloud deployment, and guide newer developers. In the near term I want to master ASP.NET Core, EF Core and SQL Server performance, then grow into Azure and system design. I would like to grow inside one company where I can take on bigger modules over time.
161

What is the difference between a clustered and a non-clustered index?

Save to ▾
Show answer
A clustered index defines the physical order of the table's data, so the leaf level is the data itself, and a table can have only one. A non-clustered index is a separate structure with key values and a pointer back to the row, and a table can have many. Range queries on the clustered key are fast. Non-clustered indexes speed up searches on other columns but add cost to inserts and updates.
162

What is the difference between a stored procedure and a user-defined function?

Save to ▾
Show answer
A stored procedure can perform inserts, updates and deletes, use transactions and TRY-CATCH, return multiple result sets and output parameters, and is called with EXEC. A function must return a value or table, cannot modify database state, and can be used inside SELECT, WHERE and JOIN. Scalar functions used row by row can hurt performance, although SQL Server 2019 and later can inline many of them.
163

Show the difference between ROW_NUMBER, RANK and DENSE_RANK with a query.

Save to ▾
Show answer
SELECT Name, Department, Salary, ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RowNum, RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS Rnk, DENSE_RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS DenseRnk FROM Employees; -- salaries 90, 90, 80 give -- ROW_NUMBER: 1, 2, 3 -- RANK: 1, 1, 3 -- DENSE_RANK: 1, 1, 2 PARTITION BY restarts numbering for each department.
164

A query that used to run in 1 second now takes 30 seconds. How do you troubleshoot it?

Save to ▾
Show answer
Capture the actual execution plan and look for table or index scans on large tables, key lookups, big differences between estimated and actual rows, and warnings like implicit conversions or spills to tempdb. Check missing or fragmented indexes and outdated statistics, and update them. Use Query Store to compare the old and new plans; if a plan regressed, you can force the good plan while fixing the root cause.
165

What is the difference between temporary tables and table variables?

Save to ▾
Show answer
Temporary tables (#Temp) live in tempdb, support indexes and statistics, and are visible to nested procedures, so they suit larger intermediate results. Table variables (@T) also use tempdb but have limited statistics, which made old optimisers estimate one row; SQL Server 2019 improved this with deferred compilation. Table variables are not affected by transaction rollback. Use table variables for small sets and temp tables for large ones.
166

Write a stored procedure that transfers money between accounts with TRY-CATCH and a transaction.

Save to ▾
Show answer
CREATE OR ALTER PROCEDURE usp_Transfer @From INT, @To INT, @Amt DECIMAL(18,2) AS BEGIN SET NOCOUNT ON; SET XACT_ABORT ON; BEGIN TRY BEGIN TRAN; UPDATE Accounts SET Balance = Balance - @Amt WHERE Id = @From AND Balance >= @Amt; IF @@ROWCOUNT = 0 THROW 50001, 'Insufficient balance', 1; UPDATE Accounts SET Balance = Balance + @Amt WHERE Id = @To; COMMIT; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK; THROW; END CATCH END
167

What is a view and what is an indexed view?

Save to ▾
Show answer
A view is a saved SELECT query that acts like a virtual table; it simplifies complex joins and can restrict which columns users see, but by default it stores no data. An indexed view has a unique clustered index, so SQL Server physically stores and maintains its results, which speeds up heavy aggregations. The cost is slower writes on base tables, and it requires SCHEMABINDING and deterministic expressions.
168

Tell me about a time you made a mistake that affected data, and what you did.

Save to ▾
Show answer
Early in my job (Situation) I ran an UPDATE on a test copy that I believed was staging, but it was a shared QA database, and 2,000 test orders lost their status. My task was to fix it fast. I told my lead immediately, restored the rows from the nightly backup with the DBA, and verified counts. Result: QA lost only an hour. Since then I always wrap manual updates in a transaction and run a SELECT with the same WHERE first.
169

Tell me about a time you worked under a tight deadline.

Save to ▾
Show answer
During my internship (Situation) a client demo was moved two days earlier, and the reports page was not ready. My task was to deliver the SQL queries and API for it. I listed must-have reports with my mentor, wrote and tested the three critical queries first, and postponed exports. I stayed in touch with the UI developer every few hours. Result: the demo went well, and we added the remaining features the next week.
170

Write a recursive CTE that lists an employee hierarchy with levels.

Save to ▾
Show answer
WITH Org AS ( SELECT Id, Name, ManagerId, 0 AS Lvl FROM Employees WHERE ManagerId IS NULL -- anchor: CEO UNION ALL SELECT e.Id, e.Name, e.ManagerId, o.Lvl + 1 FROM Employees e JOIN Org o ON e.ManagerId = o.Id -- recursive part ) SELECT REPLICATE(' ', Lvl) + Name AS Hierarchy, Lvl FROM Org OPTION (MAXRECURSION 100); The anchor query runs once and the recursive part repeats until no new rows are found.
171

What are ACID properties and the transaction isolation levels in SQL Server?

Save to ▾
Show answer
ACID means Atomicity (all or nothing), Consistency (rules hold), Isolation (transactions do not interfere) and Durability (committed data survives crashes). Isolation levels are READ UNCOMMITTED (dirty reads allowed), READ COMMITTED (the default), REPEATABLE READ, SERIALIZABLE (strictest) and SNAPSHOT, which uses row versions so readers do not block writers. Read Committed Snapshot Isolation is often enabled to reduce blocking in busy OLTP apps.
172

Users report intermittent errors saying their transaction was chosen as a deadlock victim. How do you investigate and fix it?

Save to ▾
Show answer
A deadlock happens when two sessions each hold a lock the other needs. Get the deadlock graph from the system_health Extended Events session to see the statements and objects involved. Common fixes: access tables in the same order in all code paths, keep transactions short, add indexes so queries lock fewer rows, and consider RCSI. Also add retry logic in the app, since EF Core's SQL Server execution strategy can retry deadlocks.
173

A frequent query on Orders filtered by CustomerId shows expensive key lookups in its execution plan. How would you fix it?

Save to ▾
Show answer
A covering index contains every column a query needs, so SQL Server answers it from the index alone without key lookups to the clustered index. INCLUDE adds non-key columns to the leaf level only, keeping the index key small. For SELECT Name, Total FROM Orders WHERE CustomerId = 5, an index on CustomerId INCLUDE (Name, Total) covers it. Do not include too many columns, since every index slows writes.
174

A stored procedure is fast for most customers but very slow for one large customer, and sometimes slow for everyone after a restart. What could cause this?

Save to ▾
Show answer
This is parameter sniffing. SQL Server compiles a plan using the first parameter values it sees and reuses it. A plan built for a small customer, using index seeks, can be terrible for a huge one, and vice versa. Fixes include OPTION (RECOMPILE) for that statement, OPTIMIZE FOR, splitting logic for skewed values, or Query Store plan forcing. SQL Server 2022 adds Parameter Sensitive Plan optimisation to keep multiple plans.
175

An Orders table has 50 million rows and queries are slowing down, but most reports only need the last 12 months. What would you do?

Save to ▾
Show answer
First check indexes and query plans, since good indexing often solves it. Then archive older data: move rows older than a set period to an archive table or database in small batches during off-peak hours, keeping reports on history available separately. For ongoing growth, use table partitioning by month on OrderDate, which enables fast partition switching and lets queries scan only relevant partitions. Agree retention rules with the business first.
176

Angular or React with ASP.NET Core: how do you choose?

Save to ▾
Show answer
Angular is a complete framework with routing, forms, HTTP, dependency injection and TypeScript built in, which suits large enterprise apps and teams that want strong conventions. React is a UI library with a large ecosystem, giving more freedom to pick routing and state tools, and is popular in product startups. Both work equally well with an ASP.NET Core API. Choose based on team skills, project size and the company's existing stack.
177

What are components and standalone components in Angular?

Save to ▾
Show answer
A component is a TypeScript class with the @Component decorator, a template and styles, representing one piece of UI such as a product card. Earlier, every component had to be declared in an NgModule. Standalone components import their own dependencies directly through the imports array and need no module; since Angular 19 they are the default. This simplifies apps, enables easier lazy loading and is the recommended approach in 2026.
178

Explain the types of data binding in Angular.

Save to ▾
Show answer
Interpolation {{ value }} shows component data in the template. Property binding [src]="imageUrl" sets an element or child property. Event binding (click)="save()" calls a component method on a DOM event. Two-way binding [(ngModel)]="name" combines property and event binding so the input and the field stay in sync. The first two flow from component to view, event binding flows from view to component.
179

Show the useState and useEffect hooks in a React component.

Save to ▾
Show answer
import { useState, useEffect } from 'react'; export function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const id = setInterval(() => setSeconds(s => s + 1), 1000); return () => clearInterval(id); // cleanup on unmount }, []); // empty array: run once return <p>Elapsed: {seconds}s</p>; } useState stores state that triggers re-render; useEffect runs side effects after render, and its dependency array controls when it re-runs.
180

What is the virtual DOM in React?

Save to ▾
Show answer
The virtual DOM is a lightweight JavaScript copy of the UI tree. When state changes, React renders a new virtual tree, compares it with the previous one in a process called reconciliation, and applies only the minimal changes to the real DOM, which is slow to update. Keys on list items help React match elements correctly. This lets developers write UI declaratively without manually updating DOM nodes.
181

What is the difference between props and state in React?

Save to ▾
Show answer
Props are inputs passed from a parent component to a child, like function arguments, and the child must not modify them. State is data owned and managed inside a component with useState or useReducer, and changing it re-renders the component. For example, a ProductCard receives product details as props, while a Cart component keeps the quantity in state. Shared state is lifted up to a common parent or moved into a store.
182

Your Angular app on localhost:4200 gets a CORS error when calling the ASP.NET Core API on localhost:5001. How do you fix it?

Save to ▾
Show answer
The browser blocks the call because the origins differ and the API sends no CORS headers. In the API, register a policy with AddCors allowing http://localhost:4200, the needed methods and headers, and call app.UseCors before UseAuthorization. Alternatively, use the Angular dev server proxy (proxy.conf.json) to forward /api calls, so the browser sees the same origin. In production, configure the real front-end domain, not AllowAnyOrigin.
183

Walk me through a full stack project you built.

Save to ▾
Show answer
I built an online bus-pass system (Situation) as my final project with two classmates. My task was the API and database. I designed SQL Server tables, built an ASP.NET Core Web API with EF Core and JWT login, and connected an Angular front end with reactive forms and route guards. I deployed it on Azure App Service. Result: it handled pass applications, approvals and PDF passes, and our college used it for a semester demo.
184

Why should we hire you as a .NET full stack developer?

Save to ▾
Show answer
I can contribute on both sides of a feature: I have built ASP.NET Core APIs with EF Core and SQL Server, and front ends in Angular and React, and deployed them myself. I write clean, tested code and I am comfortable reading logs and execution plans when things break. I learn quickly, ask questions early and take ownership, so you can give me a module and trust that it will be completed properly.
185

What are services and dependency injection in Angular?

Save to ▾
Show answer
A service is a class, marked @Injectable, that holds logic or data shared across components, such as API calls, authentication or a cart. Angular's DI creates the service and provides it to components that request it in the constructor or with the inject() function. With providedIn: 'root', one shared instance exists for the whole app. This keeps components focused on UI and makes logic easy to test.
186

What are signals in Angular and why were they introduced?

Save to ▾
Show answer
Signals are reactive values: count = signal(0) holds state, computed() derives values and effect() runs side effects when dependencies change. Angular knows exactly which parts of the view read which signal, so it updates only those parts instead of checking the whole component tree. This enables zoneless change detection, which became the default for new apps in Angular 21, and gives simpler state handling than RxJS for local UI state.
187

What is the difference between an RxJS Observable and a Promise?

Save to ▾
Show answer
A Promise represents a single future value, starts immediately and cannot be cancelled. An Observable can emit many values over time, is lazy until subscribed, and can be cancelled by unsubscribing. RxJS operators like map, debounceTime, switchMap and retry make it powerful for streams such as search boxes or WebSocket data. Angular's HttpClient returns Observables; use the async pipe or toSignal to avoid manual unsubscribe.
188

Write an Angular HTTP interceptor that adds a JWT to every API request.

Save to ▾
Show answer
import { HttpInterceptorFn } from '@angular/common/http'; import { inject } from '@angular/core'; export const authInterceptor: HttpInterceptorFn = (req, next) => { const token = inject(AuthService).token(); if (token) { req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next(req); }; // app.config.ts provideHttpClient(withInterceptors([authInterceptor])); Requests are immutable, so clone() creates a modified copy. The ASP.NET Core JWT middleware then reads the header.
189

Protect an Angular route so only logged-in users can open it.

Save to ▾
Show answer
import { CanActivateFn, Router } from '@angular/router'; import { inject } from '@angular/core'; export const authGuard: CanActivateFn = () => { const auth = inject(AuthService); return auth.isLoggedIn() ? true : inject(Router).createUrlTree(['/login']); }; // app.routes.ts export const routes = [ { path: 'dashboard', component: DashboardComponent, canActivate: [authGuard] }, { path: 'login', component: LoginComponent } ]; Guards only improve user experience; the API must still enforce [Authorize] on the server.
190

What is the difference between reactive forms and template-driven forms in Angular?

Save to ▾
Show answer
Template-driven forms are defined mainly in HTML with ngModel and directives; they are quick for simple forms but harder to test. Reactive forms are defined in TypeScript with FormGroup, FormControl and Validators, giving explicit, strongly typed models, easy dynamic fields, custom and async validators, and straightforward unit testing. For enterprise apps such as loan application or KYC forms, reactive forms are the usual choice.
191

Fetch products from an ASP.NET Core API in React with loading and error states.

Save to ▾
Show answer
function Products() { const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const ctrl = new AbortController(); fetch('/api/products', { signal: ctrl.signal }) .then(r => { if (!r.ok) throw new Error(r.status); return r.json(); }) .then(setItems) .catch(e => { if (e.name !== 'AbortError') setError(e.message); }) .finally(() => setLoading(false)); return () => ctrl.abort(); }, []); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return <ul>{items.map(p => <li key={p.id}>{p.name}</li>)}</ul>; }
192

What are useMemo and useCallback used for in React?

Save to ▾
Show answer
useMemo caches the result of an expensive calculation and recalculates only when its dependencies change, such as filtering 10,000 rows. useCallback caches a function reference so that a child wrapped in React.memo does not re-render just because a new function was created. Both are optimisations and add complexity, so use them where profiling shows a problem. The React Compiler, stable since late 2025, can apply much of this memoisation automatically.
193

How do you manage application state in Angular and React apps?

Save to ▾
Show answer
Start simple: local component state, then share through a parent or a service. In Angular, a service holding signals covers most needs, and NgRx or NgRx SignalStore suits large apps with complex flows. In React, Context works for low-frequency data like theme or user, Redux Toolkit or Zustand for complex client state, and TanStack Query for server data with caching. Keep server data and UI state separate.
194

Your Angular app's first load is slow on mobile because the main bundle is very large. How does lazy loading of routes help?

Save to ▾
Show answer
Lazy loading splits the app into chunks that download only when the user navigates to that route, so the initial bundle is smaller and the first page loads faster, especially on mobile data. In Angular use loadComponent or loadChildren with a dynamic import in the route config; in React use React.lazy with Suspense or the router's lazy option. Angular's @defer blocks can also delay heavy parts of a page.
195

An admin page renders 20,000 rows in a table and the browser freezes. How do you fix it?

Save to ▾
Show answer
Do not send or render everything at once. Add server-side paging, sorting and filtering in the ASP.NET Core API so the page loads perhaps 50 rows at a time. If users truly need to scroll a long list, use virtual scrolling, such as Angular CDK virtual scroll or TanStack Virtual in React, so only visible rows exist in the DOM. Also use trackBy or keys, and debounce search inputs.
196

How would you deploy an Angular or React front end together with an ASP.NET Core API?

Save to ▾
Show answer
Two common options exist. Build the SPA with ng build or npm run build and serve the static files from the API's wwwroot with UseStaticFiles and MapFallbackToFile, giving one deployment and no CORS. Or host the SPA separately on a CDN or static hosting such as Azure Static Web Apps and the API on App Service or containers, which scales independently. Use environment config for API URLs and a CI/CD pipeline for both.
197

How do you handle requirements that keep changing during a sprint?

Save to ▾
Show answer
In one sprint (Situation) the product owner changed a checkout screen twice. My task was to deliver without losing quality. I asked for a quick meeting to understand the reason, split the work into a stable API part and a flexible UI part, and agreed with the team which change would move to the next sprint. Result: we shipped the core flow on time, and the team started confirming acceptance criteria before sprint planning.
198

Your security team objects to storing the JWT in localStorage in your Angular app. What are the options?

Save to ▾
Show answer
localStorage is readable by any JavaScript on the page, so an XSS bug can steal the token. A safer pattern is to keep the short-lived access token in memory and store the refresh token in an HttpOnly, Secure, SameSite cookie that scripts cannot read. Even better is the backend-for-frontend pattern, where ASP.NET Core holds tokens server-side and the browser uses a session cookie. Add CSRF protection when using cookies.
199

A large Angular dashboard becomes sluggish because change detection runs constantly. How do OnPush and zoneless mode help?

Save to ▾
Show answer
Traditionally Zone.js patched browser events and timers, and after each one Angular checked every component for changes, top to bottom. OnPush makes a component re-check only when its inputs change by reference, an event occurs inside it, an async pipe emits or a signal it reads changes, which saves work in big screens. Zoneless mode removes Zone.js entirely and relies on signals and explicit triggers, reducing bundle size and improving performance.
200

Tell me about a time you led a team to deliver a complex feature.

Save to ▾
Show answer
As tech lead (Situation) I owned a vendor-payments module touching Angular, three APIs and SQL Server. My task was to deliver it in six weeks with four developers. I broke it into vertical slices, defined API contracts first, set up feature flags and reviewed every pull request within a day. When one developer struggled with EF Core, I paired with them. Result: we released on time with no critical bugs and two juniors grew into module owners.

Frequently asked questions

What jobs can I get after learning .NET full stack?

You can apply for roles such as .NET developer, ASP.NET Core developer, full stack .NET developer, Angular .NET developer and API developer. IT services firms, banks, insurance, healthcare, consulting and product companies in India regularly hire for these roles, especially in cities like Bengaluru, Hyderabad, Pune, Noida, Gurugram and Chennai. With experience you can grow into senior engineer, technical lead and solution architect positions working on Azure-based enterprise systems.

Who is eligible to learn .NET full stack development?

Students and graduates from B.Tech, BCA, MCA, B.Sc IT or similar backgrounds can start, and working professionals from testing, support or other languages can switch too. You do not need prior .NET experience, but basic computer skills and logical thinking help. Knowing any programming language makes the first weeks easier. Non-IT graduates can also learn it with steady practice, though they should spend extra time on programming fundamentals.

How long does it take to learn .NET full stack?

With regular study of two to three hours a day, most learners become job-ready in about four months: C# and OOP in the first month, SQL Server and EF Core next, then ASP.NET Core Web API and finally Angular or React with deployment. Building two or three complete projects is essential. Becoming confident with advanced topics like performance tuning, architecture and Azure takes further months of real work experience.

Should I learn Angular or React with .NET?

Both are in demand. Angular is very common in Indian enterprise and banking projects that use .NET, because its structure and TypeScript-first approach suit large teams. React is popular in product companies and startups. Learn one well first; Angular is a safe choice if you target IT services and enterprise roles, React if you target product firms. The concepts of components, state and API calls transfer easily between them.

Is there a certification for .NET developers?

Microsoft offers role-based certifications, and the most relevant for .NET full stack developers is Azure Developer Associate (AZ-204), which covers building and deploying apps on Azure. Microsoft Learn also offers free learning paths and credentials for C# and ASP.NET Core. Certifications help your resume, but recruiters care more about projects, GitHub code and how well you answer technical questions, so combine both.

Is .NET still in demand in 2026?

Yes. Modern .NET is open source, cross-platform and among the fastest web frameworks, and Microsoft releases a new version every November, with .NET 10 as the current long-term support release. Banks, insurers, healthcare firms, governments and global capability centres in India run large .NET systems and continue migrating old .NET Framework apps to modern .NET and Azure, which keeps steady demand for skilled developers.