36 practice questions with answers for .NET Full Stack interviews in Lucknow.
.NET Full Stack jobs in Lucknow
Lucknow's tech job market is smaller but growing, led by IT-services delivery centres, government-tech projects and start-ups. Many Lucknow candidates target Noida and Gurgaon roles or remote jobs, so interviews follow the NCR pattern.
Below are 36 questions that match the mix of service, product and domain employers hiring .net developers in Lucknow.
Solved for LucknowStart 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 controllers and Minimal APIs?
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.
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.
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.
04
Show how to bind configuration from appsettings.json using the Options pattern.
// 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.
05
Describe an API you designed end to end and the decisions you made.
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.
06
You must change an API response format, but an older mobile app version still calls it. How do you avoid breaking those users?
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.
07
Write an Angular HTTP interceptor that adds a JWT to every API request.
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.
09
A page listing 100 orders with customer names runs 101 SQL queries. What is the problem and how do you fix it?
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.
// 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.
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.
12
Demonstrate a race condition on a counter and fix it.
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.
13
Show a class using a primary constructor with dependency injection.
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.
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.
15
What is the difference between an RxJS Observable and a Promise?
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.
16
Fetch products from an ASP.NET Core API in React with loading and error states.
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.
18
A report builder concatenates 50,000 rows into one string with += and takes several seconds. What do you change?
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.
19
Which design patterns do you commonly see in ASP.NET Core projects?
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.
20
What are record types and when would you use them?
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.
21
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?
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.
22
How would you deploy an Angular or React front end together with an ASP.NET Core API?
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.
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.
25
Show bulk update and delete with ExecuteUpdate and ExecuteDelete.
// 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.
26
Show the newer LINQ methods Chunk, DistinctBy and MaxBy.
// 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.
27
Tell me about a time you refactored messy code that others depended on.
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.
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.
29
A read-only product listing endpoint in EF Core uses a lot of memory and CPU. What simple change helps, and why?
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.
30
Tell me about a time you made a mistake that affected data, and what you did.
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.
31
Show an example of the Dependency Inversion Principle in C#.
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.
32
You are designing a type to hold a 2D point used millions of times in a calculation. Struct or class?
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.
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.
34
What is the difference between a static class and a singleton?
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.
35
What is ASP.NET Core and what are its main features?
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.
36
An API endpoint calls _db.Orders.ToList().Where(o => o.CustomerId == id) and is slow as the table grows. Explain and fix it.
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.
Which companies hire .NET Full Stack professionals in Lucknow?
Companies with large offices in Lucknow include HCLTech. Use their company pages below to practise employer-specific sets.
Are .NET Full Stack interviews in Lucknow different from other cities?
The questions depend more on the company than the city. Lucknow's mix of employers decides the style: Many Lucknow candidates target Noida and Gurgaon roles or remote jobs, so interviews follow the NCR pattern
How do I find .NET Full Stack jobs in Lucknow?
Shortlist companies with Lucknow offices, keep your CV focused on .NET Full Stack projects, apply on company career pages and job portals with the Lucknow filter, and practise the questions on this page before each interview.