TL;DR: ASP.NET Core interviews in 2026 test the middleware pipeline, dependency injection lifetimes, Minimal APIs versus controllers, authentication and production hosting. Candidates should know that ASP.NET Core 10 is the current LTS version, and that it added built-in Minimal API validation and OpenAPI 3.1 by default.
ASP.NET Core 10 shipped with .NET 10 on November 11, 2025. It changed cookie auth so API endpoints return 401 and 403 instead of a redirect to a login page.
It is a small change that breaks old assumptions, and interviewers now ask about it. The fundamentals still decide most interviews: pipeline order, service lifetimes and how a request is secured.
- 1The latest patch as of September 2026 is ASP.NET Core 10.0.12, released on September 8, 2026.
- 2The rate limiting middleware rejects requests with 503 by default, not 429. Most APIs should change it.
- 3Hosted services get 30 seconds to stop by default, set by
HostOptions.ShutdownTimeout. - 4ASP.NET Core 11, now at release candidate, makes OpenAPI 3.2 the default document version.
Hosting and Pipeline
1. What does WebApplication.CreateBuilder set up for you?
It creates a host with configuration, logging, dependency injection and the Kestrel web server already wired together.
Configuration is read from appsettings.json, appsettings.{Environment}.json, user secrets (in Development), environment variables and command-line arguments.
You add services to builder.Services, call builder.Build(), then add middleware and endpoints to the returned WebApplication. The old Startup class with ConfigureServices and Configure still works.
New templates have used this single Program.cs style since .NET 6.
2. How does the middleware pipeline work, and why does order matter?
Middleware components form a chain: each one can act on the request, call the next one, then act on the response on the way back. Components run in the order they are added, so order changes behavior.

Two rules come up in every interview. UseAuthentication must come before UseAuthorization, or the user is always anonymous when policies run. The exception handler goes first, so it wraps everything else.
A component that does not call next short-circuits the pipeline, which is how static files return early. See the middleware docs for the full recommended order.
3. How do you write custom middleware?
Write a class with a constructor that takes RequestDelegate next and a method InvokeAsync(HttpContext context), then register it with app.UseMiddleware<T>().
public class TimingMiddleware(RequestDelegate next, ILogger<TimingMiddleware> log)
{
public async Task InvokeAsync(HttpContext context)
{
var sw = Stopwatch.StartNew();
await next(context);
log.LogInformation("{Path} took {Ms} ms", context.Request.Path, sw.ElapsedMilliseconds);
}
}
This kind of middleware is created once, as a singleton. So a scoped service such as a DbContext must be a parameter of InvokeAsync, not the constructor.
The other option is to implement IMiddleware, which is resolved from DI on each request.
4. When do you use middleware, an MVC filter or an endpoint filter?
Use middleware for concerns that apply to every request, before an endpoint is chosen or regardless of it: logging, headers, exception handling. Use filters when the logic needs to know about the endpoint itself.
- MVC filters (action, result, exception, authorization) run inside controllers. They can see action arguments and model state.
- Endpoint filters (
AddEndpointFilter) do the same for Minimal APIs. They receive the handler's arguments and can change or reject them.
A filter can be applied to one endpoint or a group. Middleware cannot see arguments after model binding.
5. What is Kestrel, and do you still need a reverse proxy?
Kestrel is ASP.NET Core's built-in, cross-platform web server, and it can face the internet on its own. A reverse proxy such as Nginx, YARP, IIS or a cloud load balancer is still common.
It handles TLS certificates, load balancing across instances and several apps on one IP.
Behind a proxy, the app sees the proxy's IP and scheme unless you add the Forwarded Headers middleware. Without it, HTTPS redirects loop and generated links use http.
Only trust forwarded headers from known proxies, or clients can fake their IP.
6. How does endpoint routing work?
Routing matches the request to an endpoint in UseRouting, and the endpoint runs at the end of the pipeline. Middleware between those two points can read the chosen endpoint's metadata.
Authorization, CORS and rate limiting all use it, for example to find an [Authorize] policy.
Route templates support constraints such as {id:int} and {slug:regex(...)}. Minimal APIs group routes with app.MapGroup("/orders"). The group applies one prefix, filter set and policy to all its endpoints.
Dependency Injection
7. What are the three service lifetimes, and what is a captive dependency?
Singleton means one instance for the app. Scoped means one per request. Transient means a new one each time. A captive dependency is a short-lived service held by a longer-lived one.
The classic case is a scoped DbContext injected into a singleton.

The captured DbContext is then shared by every request on every thread. It is not built for that.
DbContext can pass every test in CI and fail under load, when two requests use it at once.8. How does a singleton or background service use a scoped service?
Inject IServiceScopeFactory, create a scope for each unit of work, and resolve the scoped service from that scope.
public class Cleanup(IServiceScopeFactory scopes) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
await using var scope = scopes.CreateAsyncScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.PurgeExpiredAsync(ct);
await Task.Delay(TimeSpan.FromMinutes(5), ct);
}
}
}
Disposing the scope disposes the DbContext, so each loop gets a fresh one and no change tracker grows forever.
9. What is the difference between IOptions, IOptionsSnapshot and IOptionsMonitor?
All three give typed access to a configuration section; they differ in when they see changes.
IOptions<T>: a singleton, read once. Changes to the file are ignored until restart.IOptionsSnapshot<T>: scoped, re-read per request. It cannot be injected into a singleton.IOptionsMonitor<T>: a singleton withCurrentValueand anOnChangecallback.
Add .ValidateDataAnnotations().ValidateOnStart() when binding options. A missing connection string then fails at startup, not on the first request that needs it.
10. In what order does configuration load, and where do secrets go?
Later sources override earlier ones. The default order starts with appsettings.json and the environment file. User secrets (Development only) come next, then environment variables, then the command line.
Secrets never go in appsettings.json, which is committed to source control. Locally they go in user secrets. In production they come from environment variables or a vault such as Azure Key Vault.
Nested keys use a double underscore in environment variables: ConnectionStrings__Main sets ConnectionStrings:Main.
Building APIs
11. When do you choose Minimal APIs over controllers?
Choose Minimal APIs for new HTTP APIs unless you need something only MVC offers. Choose controllers when a team already has a large controller codebase.
They also fit when you rely on MVC features such as model binding providers or action filters.
- Classes, attributes, MVC filters
[ApiController]returns 400 on invalid models- Familiar in large, older codebases
- Lambdas or static methods, route groups
- Built-in validation since ASP.NET Core 10
- Work with Native AOT; MVC does not
Both styles can live in one app. The choice matters less than keeping one style per area of the codebase.
12. How does model binding decide where a parameter comes from?
By type and attribute. Simple types such as int and string come from the route, then the query string. Complex types come from the JSON body. Registered services are injected.
Attributes such as [FromQuery], [FromHeader], [FromBody] and [FromForm] override the default.
Minimal APIs also support [AsParameters], which binds a whole class or record from several sources at once. A body can be read only once, so an endpoint can have only one [FromBody] parameter.
13. How do you return consistent errors from an API?
Return Problem Details (RFC 9457 JSON) for every error, and handle unexpected exceptions in one place. builder.Services.AddProblemDetails() makes the framework use that format. app.UseExceptionHandler() catches unhandled exceptions.
Since .NET 8, an IExceptionHandler implementation can map known exception types to status codes, such as a NotFoundException to 404. Never return stack traces outside Development.
Since ASP.NET Core 10, exceptions that an IExceptionHandler handles are no longer logged as errors by default. That surprises teams that alert on those logs.
14. How do you version an API?
Most teams use the Asp.Versioning.Http package for Minimal APIs, or Asp.Versioning.Mvc for controllers. It reads the version from the URL segment, the query string, a header or the media type.
A strong answer is about policy as much as code: add a new version only for breaking changes. Report supported and deprecated versions in response headers, and publish a sunset date.
15. How do you add rate limiting?
Use the built-in rate limiting middleware from .NET 7: register policies with AddRateLimiter, add app.UseRateLimiter(), and attach a policy with RequireRateLimiting.
It offers fixed window, sliding window, token bucket and concurrency limiters.
builder.Services.AddRateLimiter(o =>
{
o.RejectionStatusCode = StatusCodes.Status429TooManyRequests; // default is 503
o.AddFixedWindowLimiter("api", l => { l.PermitLimit = 100; l.Window = TimeSpan.FromMinutes(1); });
});
Partition limits by user or API key, not only by IP, because many users can share one IP. These limits live in each instance's memory.
Across several instances, each keeps its own count, so a global limit needs the gateway or a shared store.
16. What is the difference between response caching, output caching and HybridCache?
They cache at different layers.
- Response caching sets HTTP cache headers and follows the client's rules, so a browser can bypass it.
- Output caching (.NET 7) stores responses on the server under rules you control, and can evict entries by tag. It can be backed by Redis since .NET 8.
- HybridCache (with .NET 9) caches data, not responses. It combines an in-memory layer with a distributed one. Only one caller rebuilds a missing entry, which stops cache stampedes.
Security
17. How does JWT bearer authentication validate a token?
The JWT bearer handler checks the token's signature against the issuer's keys, then its issuer, audience and expiry. If all pass, it builds a ClaimsPrincipal from the claims.
With an OpenID Connect authority, it downloads the signing keys from the provider. It also refreshes them on its own.
The API never calls the provider per request, so a stolen token works until it expires. Keep access tokens short-lived, and do not turn off ValidateAudience to make an error go away.
18. What is policy-based authorization, and when do you need resource-based checks?
A policy is a named set of requirements, such as "has the orders:write scope", applied with RequireAuthorization("policy") or [Authorize(Policy = "...")]. Roles are one kind of requirement; policies can check any claim or custom logic.
Policies run before the handler, so they cannot know which record the user wants. "Can this user edit this invoice?" needs a resource-based check. Load the invoice, then call IAuthorizationService.AuthorizeAsync(User, invoice, "Edit").
Missing that check is how APIs leak other users' data.
19. What does CORS protect, and what does it not?
CORS tells browsers which other origins may read your API's responses from JavaScript. It protects users' browsers, not your server. Tools like curl and other servers ignore it.
So CORS is never an access control. Avoid AllowAnyOrigin with credentials, which the framework blocks anyway. List exact origins, and call UseCors after UseRouting and before authorization.
20. When do you need antiforgery tokens?
You need them when the browser sends credentials on its own, which means cookie authentication. A malicious site can make the victim's browser submit a form to your app, and the cookie goes with it.
The antiforgery token proves the form came from your own page.
APIs that send bearer tokens in the Authorization header do not need them. A browser never adds that header by itself. Razor Pages and MVC forms validate the token by default.
Since .NET 8, Minimal API endpoints that bind form data check it too.
ASP.NET Core 11 adds a second layer that is on by default. An automatic CSRF protection middleware reads the browser's Sec-Fetch-Site and Origin headers. It rejects cross-site form posts with no token at all.
21. What is the Data Protection system, and why does it break on multiple instances?
Data Protection encrypts auth cookies, antiforgery tokens and TempData with keys the app manages. By default each instance creates and stores its own keys locally.
Behind a load balancer, instance B cannot read a cookie that instance A encrypted. Users get logged out at random. Containers lose their keys on restart for the same reason.
The fix is to store keys in one shared place, such as Redis or a database. Protect them at rest too.
Data and Production
22. What lifetime should a DbContext have, and what does pooling change?
Scoped: one DbContext per request, which AddDbContext registers by default. A DbContext is not thread-safe, so two parallel queries on one instance throw.
AddDbContextPool reuses instances across requests after resetting them, which saves setup cost in high-traffic services. The catch is that pooled contexts must not keep per-request state in fields.
Anything request-specific, such as a tenant ID, has to be set each time.
23. How do you run background work, and what happens on shutdown?
Derive from BackgroundService, register it with AddHostedService, and loop in ExecuteAsync until the token is cancelled. For work queued by requests, pair it with a bounded Channel<T>.
On shutdown, the host cancels the token and waits up to HostOptions.ShutdownTimeout, 30 seconds by default. Work that ignores the token is cut off. Queued in-memory work is lost when the process stops.
Jobs that must not be lost belong in a durable queue or a job scheduler.
24. How do health checks support Kubernetes probes?
Register checks with AddHealthChecks(), tag them, and map separate endpoints that filter by tag. The liveness endpoint reports whether the process works. The readiness endpoint reports whether it can take traffic right now.
app.MapHealthChecks("/health/live", new() { Predicate = _ => false });
app.MapHealthChecks("/health/ready", new() { Predicate = c => c.Tags.Contains("ready") });
Keep database checks off the liveness probe. If the database goes down, Kubernetes would restart every pod, which does not fix the database. See health checks in ASP.NET Core.
25. How do you write integration tests?
Use WebApplicationFactory<Program> from Microsoft.AspNetCore.Mvc.Testing. It starts the real app in memory. Its HttpClient sends requests through the full pipeline with no network.
Override services in ConfigureTestServices, for example to replace an email sender. For the database, a real engine in a container (Testcontainers) catches more bugs. The EF Core in-memory provider does not behave like SQL.
See integration tests in ASP.NET Core.
What Changed Recently
MapStaticAssets, HybridCache26. How does built-in validation work in ASP.NET Core 10 Minimal APIs?
Call builder.Services.AddValidation(), and Minimal API endpoints validate their query, header and body parameters using DataAnnotations attributes. Invalid requests get a 400 response with the errors.
Before this, Minimal APIs had no built-in validation and teams added FluentValidation or a custom endpoint filter.
The ASP.NET Core 10 release notes add a detail worth knowing: a source generator finds the types to validate, but only in the assembly where AddValidation is called. Endpoints defined in another project need their own call.
It also supports IValidatableObject for rules across several properties.
27. Why do API endpoints using cookie auth now return 401 instead of a redirect?
Since ASP.NET Core 10, cookie auth returns 401 and 403 for known API endpoints. It no longer redirects them to a login page.
Known API endpoints include [ApiController] actions, Minimal APIs that read or write JSON, endpoints returning TypedResults, and SignalR hubs.
Before, a script that called an API with an expired cookie got a 302 to an HTML login page. It then had to detect that.
Teams that relied on the redirect can restore it by overriding OnRedirectToLogin and OnRedirectToAccessDenied in the cookie options.
28. What changed in OpenAPI support from ASP.NET Core 9 to 11?
ASP.NET Core 9 added built-in OpenAPI document generation with AddOpenApi() and MapOpenApi() in the Microsoft.AspNetCore.OpenApi package. ASP.NET Core 10 made OpenAPI 3.1 the default and upgraded to Microsoft.OpenApi 2.0.
It can also emit YAML and read XML doc comments into the document.
The 3.1 switch changed schemas. Nullable types now use a type array that includes null instead of nullable: true, which can break older client generators. ASP.NET Core 11 moves the default again, to OpenAPI 3.2, per its release notes.
Both versions let you pin an older one with options.OpenApiVersion.
29. How do you stream Server-Sent Events in ASP.NET Core 10?
Return TypedResults.ServerSentEvents(stream), where the stream is an IAsyncEnumerable of items. It works in Minimal APIs and controllers. Each item can be wrapped in SseItem<T> to set an event type and ID.
app.MapGet("/prices", (CancellationToken ct) =>
TypedResults.ServerSentEvents(PriceFeed.StreamAsync(ct), eventType: "price"));
SSE is one-way, server to client, over plain HTTP. It suits live dashboards and streamed AI responses. For two-way messaging, SignalR or raw WebSockets remain the tools.
30. Which ASP.NET Core version should a team run in 2026?
ASP.NET Core 10, which ships with .NET 10 LTS and is supported until November 2028 under the .NET support policy. Versions 8 and 9 both end on November 10, 2026.
ASP.NET Core 11 is due in November 2026 as a two-year STS release. Its RC 1 adds async validation for Minimal APIs and support for C# 15 union types.
A new [ShortCircuit] attribute lets an endpoint, such as a health check, skip the rest of the pipeline. Most teams upgrade to 11 only if they need one of those features.
Signs of a Strong Answer
- They explain why authentication must run before authorization, not only that it must.
- They spot a scoped
DbContextinjected into a singleton or middleware constructor in a code sample. - They add resource-based checks for "can this user touch this record", not only a role attribute.
- They know the rate limiter returns 503 by default and change it to 429.
- They keep dependency checks off the liveness probe and can say what happens if they do not.
- They know what ASP.NET Core 10 changed for cookie auth on APIs and for OpenAPI schemas.
Hiring ASP.NET Core Developers
Many experienced ASP.NET Core engineers work remotely from Asia. Second Talent matches companies with pre-vetted .NET developers, screened with questions like these.
Tell us the stack and we send a shortlist within 24 hours. Start hiring, or see our C# and .NET and microservices interview guides.






