This is about classic ASP.NET Web API — the System.Web.Http-based framework that shipped with .NET Framework (ApiController, IHttpActionResult, OWIN, message handlers), not its spiritual successor ASP.NET Core's controllers/minimal APIs. It's still exactly what a huge number of production systems run, and exactly what most "ASP.NET Web API interview questions" banks are actually asking about. Organized by topic, with real code, a few diagrams, and a mock test at the end — and a note wherever the ASP.NET Core equivalent is worth knowing too.
ASP.NET Web API Fundamentals
Q1. What is ASP.NET Web API and what is it used for?
ASP.NET Web API is Microsoft's framework (part of .NET Framework, first shipped alongside MVC 4 in 2012) for building HTTP services — plain JSON/XML APIs consumed by browsers, mobile apps, SPAs, or other servers, as opposed to full HTML pages. It gives you a controller model (ApiController), routing, model binding, and content negotiation purpose-built for HTTP semantics rather than repurposing an MVC view-rendering pipeline for JSON.
Q2. How does ASP.NET Web API differ from WCF and ASP.NET MVC?
| WCF | ASP.NET MVC | ASP.NET Web API | |
|---|---|---|---|
| Primary purpose | Configurable services — SOAP, TCP, MSMQ, and more | HTML pages, server-rendered views | HTTP/REST services — JSON, XML |
| Protocol focus | Protocol-agnostic (bindings) | HTTP only | HTTP only, embraces verbs/status codes |
| Typical payload | SOAP/XML, or configurable | HTML | JSON (default), XML |
| Best fit today | Legacy enterprise SOAP/TCP integration | Server-rendered web apps | Public/internal REST APIs |
WCF can technically do REST too, but it was built around configurable bindings and SOAP-first thinking, which made plain REST/JSON feel bolted-on. Web API was built REST-first from day one. Against MVC: both share concepts (routing, filters, model binding), but MVC's ActionResult is built to return views/HTML, while Web API's IHttpActionResult is built around HTTP semantics — status codes, headers, and content negotiation are first-class, not an afterthought.
Q3. Explain RESTful services and how they relate to ASP.NET Web API.
REST (Representational State Transfer) is an architectural style: resources are addressed by URLs, manipulated through standard HTTP verbs, requests carry no server-side session state, and responses use standard HTTP status codes to communicate outcome. Web API doesn't force REST on you, but its whole design — routing resources to controllers, verb-based action selection, IHttpActionResult status codes — makes building a properly RESTful API the path of least resistance.
Q4. What are HTTP verbs and how are they used in Web API?
| Verb | Meaning | Typical Web API method prefix |
|---|---|---|
| GET | Read a resource, no side effects | Get… |
| POST | Create a new resource | Post… |
| PUT | Replace a resource entirely | Put… |
| PATCH | Partially update a resource | Patch… |
| DELETE | Remove a resource | Delete… |
Under convention-based routing, Web API matches the incoming HTTP verb to an action method whose name starts with that verb (GetProduct, PostProduct, DeleteProduct) — no attribute required, though [HttpGet]/[HttpPost]/etc. can override the convention explicitly, which is what attribute routing relies on instead.
Q5. How do you create a basic Web API controller?
public class ProductsController : ApiController
{
private readonly IProductRepository _repo;
public ProductsController(IProductRepository repo) => _repo = repo;
// GET api/products
public IEnumerable<Product> Get() => _repo.GetAll();
// GET api/products/5
public IHttpActionResult Get(int id)
{
var product = _repo.GetById(id);
if (product == null) return NotFound();
return Ok(product);
}
// POST api/products
public IHttpActionResult Post(Product product)
{
_repo.Add(product);
return Created($"api/products/{product.Id}", product);
}
}Every Web API controller inherits from ApiController (System.Web.Http), not MVC's Controller — a controller class must have a name ending in "Controller" for the default routing convention to find it by the {controller} route segment.
Q6. Describe routing in ASP.NET Web API.
// App_Start/WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes(); // enable [Route]/[RoutePrefix]
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}Web API supports two routing styles side by side: convention-based (one template registered once, in WebApiConfig, matching {controller}/{id} against every request) and attribute routing (each controller/action declares its own [Route]). Attribute routing, added in Web API 2, is the modern default because it expresses nested and irregular resource URLs far more naturally than one global template can.
Q7. How are requests mapped to actions in Web API?
Once routing selects a controller, action selection happens in two possible ways: by HTTP-verb-prefixed method name convention (a GET request maps to a method starting with Get), or by explicit [HttpGet]/[HttpPost]/[Route] attributes, which always win when present. If more than one action could legally handle the same request, Web API throws an ambiguous-match error (an HTTP 500, not a 404) — a classic gotcha worth knowing distinctly from an actual missing route.
Q8. What is content negotiation in the context of Web API?
Content negotiation is Web API automatically choosing the response's wire format based on what the client says it accepts — reading the Accept header (or a ?format= query string as a fallback) and picking the matching registered MediaTypeFormatter to serialize the result. The same action, returning the same C# object, can come back as JSON to one client and XML to another with zero extra code.
Content negotiation, end to end
Accept header
Client states what formats it can read
IContentNegotiator
Matches the header against registered formatters
MediaTypeFormatter
JSON, XML, BSON, or a custom formatter
Response body
Serialized in the negotiated format, Content-Type set to match
Q9. What data formats does Web API support by default for response data?
JSON (via a JsonMediaTypeFormatter, historically Newtonsoft.Json-backed) and XML (via an XmlMediaTypeFormatter using DataContractSerializer) are registered out of the box, with JSON winning by default when a request has no specific Accept header. Form-url-encoded is supported for reading request bodies. Anything else — BSON, protobuf, a custom shape — has to be added explicitly as another formatter.
Q10. How do you secure a Web API?
- Require authentication on every controller/action by default — [Authorize] applied globally, opt individual actions out with [AllowAnonymous]
- Prefer token-based auth (OAuth2 bearer tokens / JWT) over cookies for anything callable cross-origin or from non-browser clients
- Enforce HTTPS (RequireHttpsAttribute, or terminate TLS at IIS/the load balancer) and never accept credentials over plain HTTP
- Validate every model (ModelState.IsValid) before touching the database — don't trust client input
- Never bind the request body directly onto an EF entity that's then saved as-is — map through a DTO to avoid over-posting/mass-assignment
ASP.NET Web API Configuration and Hosting
Q11. How can you host an ASP.NET Web API application?
| Hosting model | Runs inside | Typical use |
|---|---|---|
| IIS / web-hosting | IIS's ASP.NET pipeline (System.Web) | Most production deployments — Azure App Service, on-prem IIS |
| Self-hosting (classic) | Your own process, via HttpSelfHostServer | Console apps, Windows Services, simple test harnesses |
| OWIN self-hosting | Your own process, via an OWIN server (e.g. Microsoft.Owin.Host.HttpListener) | Cross-cutting OWIN middleware without IIS at all |
Q12. What is OWIN and how does it relate to Web API?
OWIN (Open Web Interface for .NET) is a spec that decouples a .NET web app from any specific web server — instead of being welded to IIS/System.Web, an OWIN app is just a pipeline of middleware components, composed in a Startup class. Web API can plug into that pipeline as one piece of OWIN middleware (app.UseWebApi(config)), which is what lets it self-host outside IIS entirely, or sit alongside other OWIN middleware like the OAuth authorization server, SignalR, or custom logging — all in one process.
[assembly: OwinStartup(typeof(MyApi.Startup))]
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
}Q13. Explain the difference between self-hosting and IIS hosting in Web API.
| IIS hosting | Self-hosting | |
|---|---|---|
| Process | Runs inside w3wp.exe, managed by IIS | Runs in your own process (console app, Windows Service) |
| Lifecycle | IIS handles app pool recycling, warm-up | You own startup/shutdown entirely |
| Dependencies | System.Web / the ASP.NET pipeline | OWIN (or the older HttpSelfHostServer) |
| Typical use | Production web deployments | Tests, lightweight services, Windows Services, containers |
Q14. How do you configure CORS in Web API?
// Install-Package Microsoft.AspNet.WebApi.Cors
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute(
origins: "https://myapp.com",
headers: "*",
methods: "*");
config.EnableCors(cors);
// Or per-controller / per-action instead of globally:
// [EnableCors(origins: "https://myapp.com", headers: "*", methods: "GET,POST")]
}
}Q15. What is attribute routing and how does it improve the Web API?
[RoutePrefix("api/customers")]
public class CustomersController : ApiController
{
[Route("{customerId}/orders/{orderId}")]
public IHttpActionResult GetOrder(int customerId, int orderId) { ... }
}Attribute routing (Web API 2+) lets each action declare its own URL template directly on itself, which naturally expresses nested resources ({customerId}/orders/{orderId}) that a single global convention-based template can't express cleanly. It requires config.MapHttpAttributeRoutes() to be enabled, and can coexist with convention-based routes in the same app.
Q16. How do you handle versioning in Web API?
| Strategy | Example | Trade-off |
|---|---|---|
| URI versioning | /api/v1/products | Most visible and cacheable; clutters the URL |
| Query string | /api/products?api-version=1.0 | Easy to add; easy to omit by accident |
| Custom header | X-Api-Version: 1.0 | Keeps URLs clean; less discoverable/testable in a browser |
| Media type | Accept: application/vnd.myapp.v1+json | "Correct" REST purist approach; more complex to implement |
Classic Web API has no built-in versioning system (that arrived later, as a NuGet package and eventually natively in ASP.NET Core) — you either hand-roll one of the strategies above with route constraints/DelegatingHandlers, or adopt a community package like Microsoft.AspNet.WebApi.Versioning. Whichever strategy, the important part is picking one and being consistent about a deprecation policy.
ASP.NET Web API Request and Response
Q17. How do you handle different response status codes in Web API?
| ApiController helper | Status code |
|---|---|
| Ok() / Ok(value) | 200 OK |
| Created(uri, value) | 201 Created, with a Location header |
| BadRequest() / BadRequest(ModelState) | 400 Bad Request |
| Unauthorized() | 401 Unauthorized |
| NotFound() | 404 Not Found |
| Conflict() | 409 Conflict |
| StatusCode(HttpStatusCode) | Any specific status you need |
Q18. What is IHttpActionResult, and how does it work in action results?
IHttpActionResult (Web API 2+) is a small interface with one method — ExecuteAsync — that produces an HttpResponseMessage. Returning one from an action defers building the actual response until the framework calls that method, which is what makes Ok()/NotFound()/etc. composable, reusable, and much easier to unit test (assert on the returned result's type) than manually constructing an HttpResponseMessage inline in every action, which is how Web API 1 required it to be done.
Q19. How do you read data from the query string in Web API?
// GET api/products?category=books&minPrice=10
public IHttpActionResult Get(string category, decimal? minPrice)
{
// Simple types bind from the query string / route data by default — no attribute needed
var results = _repo.Search(category, minPrice);
return Ok(results);
}Q20. Explain the use of Request and Response message classes.
HttpRequestMessage and HttpResponseMessage (from System.Net.Http) are the actual objects flowing through the whole Web API pipeline — headers, content, status code, method, URI all live on these, and every message handler and the final action ultimately reads from one and produces the other. Even when you return IHttpActionResult, it's converting itself into an HttpResponseMessage under the hood; when you need low-level control (custom headers, streamed content, a non-standard status code path), you can build one directly with Request.CreateResponse(...).
Q21. How can you enforce SSL in a Web API action?
[RequireHttps]
public class PaymentsController : ApiController
{
// every action on this controller now rejects plain HTTP with a 403/redirect
}Q22. What is Model Binding in Web API and how is it different from MVC?
Model binding takes incoming request data (route values, query string, request body) and maps it onto action method parameters. Web API's default rules differ from MVC's in one important way: simple types (int, string, bool) bind from the URI by default, complex types bind from the request body by default — and critically, only one parameter per action can read from the body by default, since the request body stream can only be read once. MVC's model binder, by contrast, can pull multiple values from form data more freely.
Q23. How do you bind complex types in Web API?
// Implicit — Product is complex, so it's read from the body automatically:
public IHttpActionResult Post(Product product) { ... }
// Explicit, if you ever need to override the default:
public IHttpActionResult Post([FromBody] Product product) { ... }
// Multiple values needed? Wrap them in one DTO — you can't bind two
// separate complex parameters from the body in the same request.
public class CreateOrderRequest { public int CustomerId; public List<int> ProductIds; }
public IHttpActionResult Post(CreateOrderRequest request) { ... }ASP.NET Web API Serialization and Media Formats
Q24. How do you customize serialization in Web API?
var jsonFormatter = config.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings.ContractResolver =
new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;Q25. What are media type formatters in Web API?
A MediaTypeFormatter is the class responsible for turning a .NET object into bytes on the wire (and back) for one specific content type — JsonMediaTypeFormatter, XmlMediaTypeFormatter, FormUrlEncodedMediaTypeFormatter ship built in, and they're all registered in config.Formatters, where you can inspect, reconfigure, remove, or add to the list.
Q26. How do you support XML or JSON, or other formats as a response in Web API?
// Both are already registered by default — nothing to add for JSON/XML.
// Remove one if you want to force a single format app-wide:
config.Formatters.Remove(config.Formatters.XmlFormatter);
// Add a new one for a format neither covers out of the box:
config.Formatters.Add(new BsonMediaTypeFormatter());Q27. What is BSON and how can it be used with Web API?
BSON (Binary JSON) is a compact binary encoding of JSON-like documents — smaller and faster to parse than text JSON for large payloads, at the cost of not being human-readable. Web API 2.1+ ships BsonMediaTypeFormatter out of the box; register it in config.Formatters and a client that sends Accept: application/bson gets binary-encoded responses instead of text JSON.
Q28. How do you return a custom response format from an action?
public HttpResponseMessage GetReport()
{
var csv = _reportService.BuildCsv();
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(csv);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
return response;
}ASP.NET Web API Action Filters and Handlers
Q29. What are DelegatingHandlers in Web API?
A DelegatingHandler is a pipeline stage that sits before routing and controller selection even happen — it receives the raw HttpRequestMessage, can short-circuit or modify it, calls base.SendAsync to hand off to the next handler in the chain, and can inspect/modify the HttpResponseMessage on the way back out. It's the message-handler-level equivalent of ASP.NET Core middleware, and the natural place for cross-cutting concerns that need to run outside — and before — any filter or controller logic.
The classic Web API pipeline, request in → response out
Message handlers
DelegatingHandlers — outermost, runs before routing
Routing
Matches the URL + verb to a controller/action
Authentication / Authorization filters
Who is this, and are they allowed?
Action filters + the action
Model binding, then your controller method runs
public class RequestTimingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken ct)
{
var sw = Stopwatch.StartNew();
var response = await base.SendAsync(request, ct); // hand off downstream
response.Headers.Add("X-Elapsed-Ms", sw.ElapsedMilliseconds.ToString());
return response;
}
}
// Registration:
config.MessageHandlers.Add(new RequestTimingHandler());Q30. How do you implement Action Filters in Web API?
public class LogActionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext ctx)
{
Trace.WriteLine($"Executing {ctx.ActionDescriptor.ActionName}");
}
public override void OnActionExecuted(HttpActionExecutedContext ctx)
{
Trace.WriteLine($"Executed {ctx.ActionContext.ActionDescriptor.ActionName}");
}
}
// Usage:
[LogAction]
public IHttpActionResult Get(int id) { ... }Q31. Explain the difference between action filters and authorization filters.
| Authorization filters | Action filters | |
|---|---|---|
| Interface | IAuthorizationFilter | IActionFilter |
| Runs | Before model binding, before the action | Immediately around the action call |
| Purpose | Decide whether the caller may proceed at all | Cross-cutting logic around a call that's already allowed |
| Typical example | [Authorize], a custom claims check | Logging, validation, response shaping |
Q32. How can you implement custom authentication in Web API?
public class ApiKeyAuthHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken ct)
{
if (!request.Headers.TryGetValues("X-Api-Key", out var keys) ||
!_validKeys.Contains(keys.First()))
{
return request.CreateResponse(HttpStatusCode.Unauthorized);
}
return await base.SendAsync(request, ct);
}
}A DelegatingHandler works for coarse, pipeline-wide auth like an API key check. For principal-aware auth that needs to populate User/ClaimsPrincipal for later filters and actions to see, Web API 2's IAuthenticationFilter (or OWIN authentication middleware sitting in front of Web API entirely) is the more correct tool.
Q33. What is message lifecycle in ASP.NET Web API?
A request's full journey: it arrives at the host (IIS or self-host), passes through every registered DelegatingHandler in order, gets routed to a controller/action, runs through authentication then authorization filters, has its parameters model-bound, runs through action filters (before), executes the action, runs action filters (after), and — if anything threw — exception filters get a chance to convert the error into a proper response, before the message travels back out through the same DelegatingHandlers in reverse.
ASP.NET Web API Dependency Injection and Testing
Q34. How do you implement Dependency Injection in ASP.NET Web API?
Unlike ASP.NET Core, classic Web API has no built-in DI container — you plug in a third-party one (Unity, Autofac, Ninject, StructureMap were the common choices) by implementing IDependencyResolver and assigning it to config.DependencyResolver. Once wired up, controllers just take their dependencies as constructor parameters exactly like in modern .NET.
// Autofac example
var builder = new ContainerBuilder();
builder.RegisterType<ProductRepository>().As<IProductRepository>();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);Q35. What frameworks are useful for testing Web API applications?
| Concern | Common tooling |
|---|---|
| Unit testing | xUnit, NUnit, or MSTest — same as anywhere else in .NET |
| Mocking | Moq, NSubstitute — fake out IProductRepository etc. |
| Integration testing | Microsoft.Owin.Testing.TestServer (in-memory OWIN pipeline) |
| Manual/exploratory | Postman, Fiddler, curl |
Q36. Explain the process of unit testing in ASP.NET Web API.
[Fact]
public void Get_ReturnsNotFound_WhenProductMissing()
{
var repo = new Mock<IProductRepository>();
repo.Setup(r => r.GetById(99)).Returns((Product)null);
var controller = new ProductsController(repo.Object);
var result = controller.Get(99);
Assert.IsType<NotFoundResult>(result);
}Because a controller's dependencies are just constructor parameters, testing one is as simple as constructing it directly with mocked dependencies and calling the action — no web server needs to be running. IHttpActionResult's concrete return types (OkNegotiatedContentResult<T>, NotFoundResult, etc.) make assertions on the outcome straightforward without inspecting raw HTTP responses.
ASP.NET Web API and Entity Framework
Q37. How can you integrate Entity Framework with Web API?
public class ProductsController : ApiController
{
private readonly AppDbContext _db = new AppDbContext();
public IHttpActionResult Get(int id)
{
var product = _db.Products.Find(id);
return product == null ? (IHttpActionResult)NotFound() : Ok(product);
}
protected override void Dispose(bool disposing)
{
if (disposing) _db.Dispose();
base.Dispose(disposing);
}
}Classic Web API controllers are created fresh per request but don't get a scoped DI lifetime unless you've wired one up (see the DI question above) — so a DbContext either gets constructed directly per controller (and disposed in an overridden Dispose, as above) or is resolved per-request through whichever container you're using, configured with a per-request lifetime scope.
Q38. Describe the best practices for using Entity Framework with Web API.
- Scope the DbContext to one request — never share/cache one across requests, it isn't thread-safe
- Return DTOs, not EF entities, from actions — avoids leaking internal schema and serialization cycles on navigation properties
- Use async EF methods (ToListAsync, FindAsync) in async actions to avoid blocking request threads
- Turn on lazy-loading only where you actually need it — accidental N+1 queries are easy to introduce through navigation properties
- Wrap multi-step writes in an explicit transaction if they must succeed or fail together
Advanced ASP.NET Web API Topics
Q39. How does Web API implement OData?
The Microsoft.AspNet.OData package lets a Web API controller expose queryable, filterable, sortable collections following the OData standard — a client can append $filter, $orderby, $top, $expand directly to the URL and the framework translates them into the equivalent LINQ query, without you writing that plumbing by hand.
public class ProductsController : ODataController
{
[EnableQuery]
public IQueryable<Product> Get() => _db.Products;
}
// GET /odata/Products?$filter=Price gt 50&$orderby=Name&$top=10Q40. What are action selectors?
An action selector is the mechanism (IHttpActionSelector) that decides which of a controller's methods should actually handle an incoming request. When the convention/attribute matching is ambiguous — say two Get methods that could both match — [ActionName("Search")] or [NonAction] let you steer the selection explicitly instead of relying on the default heuristic.
Q41. Explain the use of Exception Filters in your API.
public class ApiExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext ctx)
{
ctx.Response = ctx.Request.CreateResponse(
HttpStatusCode.InternalServerError,
new { error = ctx.Exception.Message });
}
}Exception filters convert an unhandled exception thrown by an action (or another filter) into a well-formed HttpResponseMessage instead of letting it bubble up as a raw 500. Important limitation: they only catch exceptions from the filter/action pipeline — an exception thrown inside a DelegatingHandler happens before this stage and won't be caught here, which is exactly why Web API 2 added IExceptionHandler/IExceptionLogger as a true global backstop.
Q42. What are the benefits of using async and await in Web API?
The same reason it matters everywhere in .NET: an await releases the current thread back to the pool while waiting on I/O (a database call, an outbound HTTP call), instead of blocking it — which matters a lot under IIS's classic thread-pool-per-request model, where thread starvation under load is a real, well-documented failure mode. The one genuinely classic-ASP.NET-specific risk: blocking on a Task with .Result or .Wait() inside a request can deadlock, because of the ambient SynchronizationContext that classic ASP.NET (unlike ASP.NET Core) captures — always await all the way down.
Q43. How can you handle file uploads in Web API?
public async Task<IHttpActionResult> Upload()
{
if (!Request.Content.IsMimeMultipartContent())
return BadRequest("Expected multipart content");
var provider = new MultipartFormDataStreamProvider(
System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data/uploads"));
await Request.Content.ReadAsMultipartAsync(provider);
return Ok(provider.FileData.Select(f => f.LocalFileName));
}Q44. Discuss SignalR and its integration with ASP.NET Web API.
The original ASP.NET SignalR (not to be confused with ASP.NET Core's SignalR) can run inside the same OWIN pipeline as Web API — app.MapSignalR() and app.UseWebApi(config) in the same Startup class — so a single app serves both REST CRUD endpoints and real-time Hub connections (chat, live dashboards, push notifications) side by side.
ASP.NET Web API Performance
Q45. What are some performance optimization strategies for Web API?
- Use async actions for anything I/O-bound to avoid starving the thread pool under load
- Enable response compression (gzip/deflate) for larger JSON/XML payloads
- Cache expensive/rarely-changing responses server-side (MemoryCache/Redis) instead of recomputing every request
- Support pagination on large collection endpoints instead of returning everything at once
- Trim the formatter list to just what you actually need — fewer registered formatters means less content-negotiation overhead per request
Q46. How do you implement caching in Web API?
public IHttpActionResult Get(int id)
{
var cacheKey = $"product-{id}";
if (MemoryCache.Default[cacheKey] is Product cached) return Ok(cached);
var product = _repo.GetById(id);
if (product != null)
MemoryCache.Default.Set(cacheKey, product, DateTimeOffset.UtcNow.AddMinutes(5));
return product == null ? (IHttpActionResult)NotFound() : Ok(product);
}| Layer | Mechanism |
|---|---|
| Client-side | Cache-Control / ETag headers, conditional GET → 304 Not Modified |
| Server-side, in-process | System.Runtime.Caching.MemoryCache |
| Server-side, distributed | Redis (StackExchange.Redis) shared across instances |
| Edge / gateway | IIS output caching, a CDN in front of the API |
Q47. What role does HttpResponseMessage play in Web API performance?
Because HttpResponseMessage exposes the raw HttpContent, you can stream a response (PushStreamContent/StreamContent) instead of buffering an entire payload in memory before sending it — important for large files or reports. It also lets you set precise caching/compression headers per response and avoid the overhead of a formatter round-trip when you already have the exact bytes you want to send.
ASP.NET Web API Security
Q48. What are the different ways to authenticate users in Web API?
| Scheme | How it works |
|---|---|
| Basic Auth | Username:password base64-encoded in the Authorization header |
| Windows/Integrated | IIS-negotiated, intranet-only, ties identity to the domain account |
| Token-based (OAuth2 bearer) | OWIN OAuth middleware issues a token, validated on each request |
| API keys | A pre-shared secret in a header, checked by a filter/handler |
| Claims-based | A ClaimsPrincipal populated by upstream auth middleware |
Q49. How do you implement OAuth2 authorization in Web API?
public void Configuration(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/token"),
Provider = new SimpleAuthorizationServerProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
AllowInsecureHttp = false,
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}OWIN OAuth2 bearer token flow
POST /token
Client sends credentials (grant_type=password, etc.)
Authorization server middleware
Validates credentials, issues a signed bearer token
Authorization header
Client sends the token on every request after
OAuthBearerAuthentication
Validates the token, populates the ClaimsPrincipal
Q50. Explain token-based authentication in Web API.
Instead of a server-side session and a cookie, the client authenticates once, receives an opaque or self-contained (JWT) token, and attaches it as Authorization: Bearer <token> on every subsequent request. The server validates the token on each request (signature, expiry, issuer) and populates the request's identity from its claims — no server-side session state to manage, which is exactly what makes this scale horizontally and work naturally for non-browser clients.
ASP.NET Web API Client-Side
Q51. How can a client consume a Web API?
using var client = new HttpClient { BaseAddress = new Uri("https://api.example.com/") };
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("api/products/5");
response.EnsureSuccessStatusCode();
var product = await response.Content.ReadAsAsync<Product>();Since it's just HTTP+JSON, literally any HTTP-capable client can consume it — .NET's own HttpClient, JavaScript's fetch, Python's requests, Postman, or curl. That protocol-agnosticism on the client side is the whole point of a REST API over something like classic WCF's tighter binding-specific contracts.
Q52. Discuss different client libraries available for accessing ASP.NET Web API.
- HttpClient (System.Net.Http) — the canonical .NET client, works everywhere .NET runs
- RestSharp — a popular third-party wrapper with convenience features on top of HttpClient
- Generated proxies — NSwag/Swagger Codegen can produce a typed client straight from the API's OpenAPI/Swagger spec
- Any non-.NET HTTP client — axios/fetch in JS, requests in Python — since the wire format is just JSON over HTTP
Q53. What is Swagger, and how does it integrate with Web API?
Swagger (now standardized as OpenAPI) is a machine-readable description of an API's endpoints, parameters, and response shapes — which powers interactive documentation (Swagger UI) and client code generation. For classic Web API, the Swashbuckle NuGet package inspects your controllers/attributes/XML doc comments at startup and generates that spec plus a browsable UI automatically, with no manual spec-writing required.
ASP.NET Web API Troubleshooting
Q54. How do you handle errors globally in ASP.NET Web API?
public class GlobalExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
context.Result = new ResponseMessageResult(
context.Request.CreateResponse(HttpStatusCode.InternalServerError,
new { error = "An unexpected error occurred." }));
}
}
// Registration (Web API 2+):
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());IExceptionHandler (Web API 2+) is the true app-wide backstop — unlike an exception filter, it runs for exceptions the filter pipeline itself can't catch, giving every unhandled error one consistent shape without repeating try/catch in every action. Pair it with IExceptionLogger for logging errors even when something else ultimately handles the response.
Q55. What is a common cause for a 404 not found error in Web API and how can it be resolved?
- The route template genuinely doesn't match the request URL — check WebApiConfig / [Route] against the exact path being called
- Attribute routing isn't enabled (missing config.MapHttpAttributeRoutes()) so [Route] attributes are silently ignored
- The controller class name doesn't end in "Controller", so the {controller} convention can't find it
- Wrong HTTP verb used against a route that only maps one verb — note this is more correctly a 405 Method Not Allowed, but is easy to misdiagnose as a 404
ASP.NET Web API Best Practices
Q56. Discuss some best practices for API versioning.
Pick one strategy (URI, header, or media-type) and apply it consistently everywhere rather than mixing approaches per endpoint. Version from day one even if v1 is the only version that exists yet — retrofitting versioning onto live clients later is far more painful than starting with it. Publish a clear deprecation timeline for old versions instead of silently breaking or silently keeping them forever.
Q57. How can you make your Web API more RESTful?
- Model URLs around nouns/resources (/products/5), not verbs (/getProduct?id=5)
- Use the HTTP verb to express the action instead of encoding it in the URL
- Return the correct status code for every outcome, not just 200 with an error flag buried in the body
- Keep it stateless — no server-side session tied to a specific request
- Use plural nouns and consistent nesting for related resources (/customers/5/orders)
Q58. What are some common security issues to be aware of when developing a Web API?
- Over-posting / mass assignment — binding a request body straight onto an EF entity lets a client set fields it should never control
- Insecure direct object references — an /orders/{id} endpoint with no ownership check lets any authenticated user read anyone's order
- Verbose error responses leaking stack traces or internal exception details to the client
- CORS configured too permissively (wildcard origin combined with credentials)
- Missing rate limiting on expensive or sensitive endpoints, inviting abuse
Q59. What are some common patterns used in API development?
- Repository + Unit of Work — abstracting data access behind an interface
- DTO + AutoMapper — decoupling the wire contract from internal/EF entities
- Facade / service layer — controllers stay thin, business logic lives in services
- API Gateway / Backend-for-Frontend — one entry point fronting several services
- Pagination and idempotency-key patterns for large collections and safe POST retries
Q60. How do you manage large-scale API development and multiple teams?
Agree the contract first (an OpenAPI/Swagger spec teams sign off on before building against each other), version deliberately, keep shared concerns (auth, DTOs, error shapes) in common libraries rather than each team reinventing them, and use contract testing (e.g. Pact) so one team can't silently break another's integration without a failing test surfacing it immediately.
Q61. Describe some anti-patterns to avoid in Web API development.
- A "god controller" handling every unrelated concern instead of being scoped to one resource
- Leaking EF/domain entities directly as the response shape instead of a stable DTO contract
- Chatty APIs that force clients into many round trips for what should be one call
- Always returning 200 OK with a success/error flag in the body instead of using real status codes
- No versioning strategy until a breaking change is already unavoidable
ASP.NET Web API Design and Architecture
Q62. When should you use ASP.NET Web API over other technologies?
Choose it (or its ASP.NET Core successor) whenever the goal is a plain HTTP/JSON service consumed by browsers, mobile apps, or other services — and reach for WCF instead only when you genuinely need protocol flexibility beyond HTTP (TCP, MSMQ) or are integrating with an existing SOAP-based enterprise system. For brand-new projects today, ASP.NET Core's Web API support is the better default unless you're specifically constrained to .NET Framework.
Q63. How can you design a scalable API using ASP.NET Web API?
- Keep it stateless so any instance behind a load balancer can serve any request
- Push session/cache state to something shared (Redis) once you're running more than one instance
- Use async I/O throughout to avoid thread-pool exhaustion under concurrent load
- Paginate large collection endpoints instead of returning unbounded result sets
- Offload long-running work to a queue/background worker instead of blocking the request
Q64. Describe a microservices architecture with reference to ASP.NET Web API.
Each service is its own Web API project (its own IIS site, app pool, or self-hosted OWIN process) owning one bounded context and its own database, talking to other services over HTTP or a message broker rather than sharing a database. The principles are identical to microservices built on any stack — the .NET-Framework-specific wrinkle is that hosting/scaling tends to lean on IIS app pools or Windows Services/VMs rather than the container-first approach that's more natural with .NET Core.
Q65. What is the Repository pattern and how does it apply to Web API?
public interface IProductRepository
{
Product GetById(int id);
IEnumerable<Product> GetAll();
void Add(Product product);
}
public class ProductsController : ApiController
{
private readonly IProductRepository _repo;
public ProductsController(IProductRepository repo) => _repo = repo;
// controller stays thin — no direct DbContext/SQL here
}Wrapping data access behind an interface decouples controllers from EF specifically, and makes them trivially unit-testable with a mock repository instead of a real database.
Miscellaneous Topics on ASP.NET Web API
Q66. What is Web API OWIN middleware?
It means two related things: Web API itself running as one piece of OWIN middleware (app.UseWebApi(config)), and the other OWIN middleware components — CORS, OAuth, custom logging, static files — that compose around it in the same pipeline, each able to inspect or short-circuit the request before it ever reaches Web API's own routing.
Q67. How can you document your Web API?
Swashbuckle (Swagger/OpenAPI generation + interactive UI) is the most common modern choice; the older Microsoft.AspNet.WebApi.HelpPage NuGet package generates browsable docs from XML doc comments if you'd rather not adopt Swagger. Either way, pair generated docs with a maintained Postman collection so consumers have working, runnable examples, not just a schema.
Q68. Describe how you would implement rate limiting in ASP.NET Web API.
public class ThrottlingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken ct)
{
var clientId = request.Headers.GetValues("X-Api-Key").First();
var key = $"throttle-{clientId}";
var count = (int?)MemoryCache.Default[key] ?? 0;
if (count >= 100)
return request.CreateResponse((HttpStatusCode)429, "Rate limit exceeded");
MemoryCache.Default.Set(key, count + 1, DateTimeOffset.UtcNow.AddMinutes(1));
return await base.SendAsync(request, ct);
}
}Classic Web API has no built-in rate limiter (that's an ASP.NET Core 7+ feature) — a DelegatingHandler tracking a counter per client key in MemoryCache (or Redis for a multi-instance deployment) is the standard hand-rolled approach, though the WebApiThrottle NuGet package is a well-known ready-made alternative.
ASP.NET Web API and Globalization
Q69. How do you support multiple languages in Web API?
public class CultureHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken ct)
{
var lang = request.Headers.AcceptLanguage.FirstOrDefault()?.Value ?? "en-US";
Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
return base.SendAsync(request, ct);
}
}Q70. What is localization and how can it be applied in Web API?
Localization is presenting content (error messages, labels, formatted numbers/dates) appropriate to the caller's culture. In classic Web API, that's typically .resx resource files per culture, selected based on the Accept-Language header (via the handler above), with ResourceManager.GetString(key) pulling the right localized string for whatever culture got set on the current thread.
ASP.NET Web API Routing
Q71. Explain convention-based routing in Web API.
One route template, registered once in WebApiConfig, matched against every request's URL structure and HTTP verb — {controller}/{id} maps /api/products/5 to ProductsController, and the verb (GET/POST/etc.) picks the action by the Get.../Post... method-name convention. It's simple and requires no per-action annotation, but scales poorly once URLs need to express real resource nesting.
Q72. What are the limitations of convention-based routing and how can they be overcome?
Nested resource URLs (/customers/5/orders/12) don't fit one flat {controller}/{id} template; multiple actions responding to the same verb on the same controller create ambiguous matches the verb-prefix convention can't resolve on its own. Attribute routing ([Route]/[RoutePrefix] per action) solves both — it's why Web API 2 introduced it, and why most real projects use attribute routing as the primary strategy today, convention-based routing as a simple fallback at most.
Q73. How can you define optional parameters in the route?
// Convention-based:
config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
// Attribute routing:
[Route("api/products/{id?}")]
public IHttpActionResult Get(int? id) { ... }Q74. What is route constraint in Web API and how do you use it?
[Route("api/products/{id:int:min(1)}")]
public IHttpActionResult Get(int id) { ... }A route constraint restricts which values a route segment will match — {id:int} only matches numeric segments, so a request for /api/products/abc won't even reach this action (it'll 404 or fall through to another matching route), rather than reaching the action and failing model binding. For anything a built-in constraint can't express, implement IHttpRouteConstraint directly.
ASP.NET Web API and Data Transfer Objects (DTOs)
Q75. What are DTOs and why are they important in Web API?
A DTO (Data Transfer Object) is a plain class shaping exactly what goes over the wire, deliberately separate from your EF/domain entities. It prevents over-posting (a client can't set fields on the DTO that don't exist on it), decouples the public API contract from internal schema changes, and lets you hide sensitive or irrelevant internal fields entirely.
Q76. Explain how to use AutoMapper in ASP.NET Web API.
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Product, ProductDto>();
cfg.CreateMap<ProductDto, Product>();
});
public IHttpActionResult Get(int id)
{
var product = _repo.GetById(id);
return product == null ? (IHttpActionResult)NotFound() : Ok(Mapper.Map<ProductDto>(product));
}ASP.NET Web API Action Results
Q77. What are the advantages of using IHttpActionResult?
It defers response construction to a small, testable object instead of hand-assembling an HttpResponseMessage inline, making actions easier to read, easier to unit test (assert on the result's concrete type), and easier to compose — a custom IHttpActionResult can encapsulate a whole reusable response shape used across many actions.
Q78. Differentiate between Ok, BadRequest, NotFound, and other action results in Web API.
| Result | Status | When to use it |
|---|---|---|
| Ok() / Ok(value) | 200 | The request succeeded, optionally with a payload |
| BadRequest() / BadRequest(ModelState) | 400 | The request itself was malformed or invalid |
| Unauthorized() | 401 | The caller isn't authenticated at all |
| NotFound() | 404 | The requested resource doesn't exist |
| Conflict() | 409 | The request conflicts with the resource's current state |
ASP.NET Web API and Asynchronous Programming
Q79. Discuss the benefits and risks of using asynchronous controllers in Web API.
Benefit: threads aren't blocked waiting on I/O, so the app handles far more concurrent requests with the same thread pool. Risk: mixing blocking calls (.Result, .Wait()) into what should be an all-async call chain can deadlock under classic ASP.NET's SynchronizationContext — a mistake that's much less dangerous (and often simply doesn't happen) in ASP.NET Core, which has no such context by default.
Q80. Give an example of how to implement an asynchronous action in Web API.
public async Task<IHttpActionResult> Get(int id)
{
var product = await _repo.GetByIdAsync(id);
return product == null ? (IHttpActionResult)NotFound() : Ok(product);
}ASP.NET Web API and Content Negotiation
Q81. Define content negotiation and its role in a Web API application.
It's the mechanism that decides, per request, which format a response comes back in — JSON, XML, or anything else registered — based on what the client's Accept header says it can consume, without the action code needing to know or care which format ultimately gets picked.
Q82. How do you force Web API to return a specific content type?
public HttpResponseMessage Get(int id)
{
var product = _repo.GetById(id);
return Request.CreateResponse(HttpStatusCode.OK, product, new JsonMediaTypeFormatter());
}ASP.NET Web API and Security Features
Q83. How do you implement claims-based authentication in Web API?
public IHttpActionResult Get()
{
var principal = (ClaimsPrincipal)User;
if (!principal.HasClaim("department", "finance")) return Unauthorized();
return Ok(_repo.GetFinanceReports());
}Once upstream OWIN authentication middleware has populated the request's identity as a ClaimsPrincipal, any action (or a custom AuthorizeAttribute override) can check specific claim types instead of coarse role names — more flexible for permission models that don't map cleanly onto a small fixed set of roles.
Q84. Explain Cross-Site Request Forgery (CSRF) protection in Web API.
CSRF exploits the browser automatically attaching cookies to a request the user didn't intend to make — it's fundamentally a cookie-auth problem. A Web API using bearer/OAuth tokens attached explicitly by client-side JavaScript is largely immune by construction, since a malicious third-party site can't read the token to attach it itself. CSRF only becomes a real concern for a Web API when it's authenticated via a shared cookie (commonly alongside an MVC app on the same domain).
Q85. How does anti-forgery token work in Web API and when should you use it?
The classic ASP.NET anti-forgery mechanism issues a token tied to the user's session (via System.Web.Helpers.AntiForgery), which the client must echo back — traditionally as a hidden form field, but for an API, as a custom header set by JavaScript — and the server validates that the two match. It's only necessary when cookie-based auth is in play; a purely bearer-token API doesn't need it.
ASP.NET Web API Caching
Q86. What are the different caching mechanisms available to a Web API?
| Mechanism | Where it lives |
|---|---|
| Cache-Control / ETag headers | Client / intermediary caches |
| System.Runtime.Caching.MemoryCache | In-process, one server instance |
| Redis (StackExchange.Redis) | Shared across multiple instances |
| Reverse proxy / CDN caching | In front of the API entirely |
Q87. How does server-side caching work in Web API?
An action checks a cache (MemoryCache/Redis) for a previously computed result keyed by the request's parameters before touching the database or running expensive logic; on a miss, it computes the result, stores it with an expiration policy, then returns it — on a hit, it skips straight to returning the cached value. Pairing this with client-facing Cache-Control/ETag headers lets well-behaved clients skip the round trip entirely on top of the server-side savings.
ASP.NET Web API and Middleware
Q88. Explain the role of middleware in the ASP.NET Web API pipeline.
"Middleware" here really means the surrounding OWIN pipeline (when self-hosted, or hosted via OWIN on IIS) — components that wrap the entire Web API app the same way ASP.NET Core middleware wraps a Core app. Web API's own DelegatingHandlers are a second, inner layer of essentially the same idea, specific to Web API's own sub-pipeline once OWIN has already handed the request in.
Q89. How can middleware be used to implement cross-cutting concerns?
Logging every request/response, enforcing global authentication, adding a correlation ID to every log line and response header, compressing responses, or rate limiting — all of it written once as OWIN middleware (or a DelegatingHandler) instead of copy-pasted into every controller.
ASP.NET Web API and Deployment
Q90. What are some considerations when deploying a Web API to Azure?
Classic Web API needs the full .NET Framework, so it targets Windows-based Azure App Service (or a Windows VM/Cloud Service) — it can't run on Linux App Service the way .NET Core can. Beyond that: connection strings and secrets belong in App Service configuration (or Key Vault), not web.config in source control; scale-out settings and health probes matter the same way they do for any horizontally-scaled service.
Q91. How do you enable HTTPS for a Web API on Azure?
Bind a certificate (an Azure-managed free certificate, or your own) to a custom domain in the App Service's TLS/SSL settings, and turn on the "HTTPS Only" toggle so Azure itself redirects any plain HTTP traffic. Applying [RequireHttps] at the application level too is good defense-in-depth in case that setting ever gets missed during a redeploy.
ASP.NET Web API Advanced Topics
Q92. What are HATEOAS and its importance in RESTful APIs?
HATEOAS (Hypermedia As The Engine Of Application State) is the most mature level of the Richardson Maturity Model for REST — responses include links describing what a client can do next (an order response includes a "cancel" link only if it's still cancellable), so the client discovers available actions from the response itself instead of hardcoding every URL up front. It's honestly rare to see fully implemented in real-world APIs, but it's a genuinely useful concept to understand — and interviews tend to test recognition of the idea more than expecting you to have shipped it.
Q93. Explain how to implement HATEOAS in an ASP.NET Web API.
public class OrderDto
{
public int Id { get; set; }
public string Status { get; set; }
public List<LinkDto> Links { get; set; } = new();
}
public IHttpActionResult Get(int id)
{
var order = _repo.GetById(id);
var dto = Mapper.Map<OrderDto>(order);
dto.Links.Add(new LinkDto { Rel = "self", Href = Url.Link("DefaultApi", new { id }) });
if (order.CanCancel)
dto.Links.Add(new LinkDto { Rel = "cancel", Href = Url.Link("CancelOrder", new { id }) });
return Ok(dto);
}ASP.NET Web API and Monitoring
Q94. What tools can you use to monitor the health and performance of your Web API?
- Application Insights — the classic .NET Framework SDK works fine with Web API, not just ASP.NET Core
- APM agents (New Relic, Datadog) for request tracing and performance breakdowns
- IIS logs and Windows Event Viewer for host-level issues
- A hand-rolled /api/health endpoint — classic Web API has no built-in Health Checks middleware the way ASP.NET Core does
Q95. How can you log API requests and responses?
A DelegatingHandler reading (and carefully re-buffering) the HttpRequestMessage/HttpResponseMessage content on the way in and out, writing structured entries through log4net/NLog/Serilog (all of which run fine on .NET Framework) — the same architectural spot as the request-timing handler shown earlier, just logging instead of timing.
ASP.NET Web API Testing and Troubleshooting
Q96. What approaches can you take to troubleshoot a failing Web API?
- Reproduce the exact request with Postman/Fiddler to rule out a client-side mistake first
- Enable Web API tracing (ITraceWriter) to see the framework's own pipeline decisions
- Check IIS/OWIN startup logs and the Windows Event Viewer for host-level failures
- Inspect the registered route table (config.Routes) to confirm the request should even match anything
- Watch for the classic "double serialization"/formatter conflict when two formatters both claim a content type
Q97. How can integration testing be implemented for a Web API?
using (var server = TestServer.Create(app => Startup.ConfigureAuth(app)))
{
var response = await server.HttpClient.GetAsync("/api/products");
response.EnsureSuccessStatusCode();
}Microsoft.Owin.Testing.TestServer spins up the real OWIN pipeline — real routing, real filters, real message handlers — entirely in memory, so integration tests exercise the actual request path without needing IIS or a real network call.
ASP.NET Web API and Interoperability
Q98. How can you ensure your Web API is consumable by a wide range of clients?
Stick to standard JSON over HTTP as the primary format (support XML too only if your actual audience needs it), publish an OpenAPI/Swagger spec so any language's tooling can generate a client, version predictably, and avoid platform-specific auth schemes (like Windows/Integrated auth) if clients outside your own network need to call in.
Q99. What is JSONP, and how can it be used with Web API?
JSONP ("JSON with Padding") is a pre-CORS workaround for cross-domain requests — it wraps the JSON payload in a client-specified function call (?callback=myFn returns myFn({...})) so it can be loaded via a <script> tag, which the old same-origin policy didn't block. Classic Web API supports it via an add-on JsonpMediaTypeFormatter, but it's effectively obsolete now that CORS is universally supported, and it's worth flagging as a real security smell (it's arbitrary script execution by design) rather than recommending it today.
ASP.NET Web API Emerging Technologies and Trends
Q100. How can ASP.NET Web API leverage new technologies like Docker and Kubernetes?
Classic Web API needs the full .NET Framework, so it has to run in a Windows container (the mcr.microsoft.com/dotnet/framework/aspnet base images) rather than the much lighter, more mature Linux container ecosystem — and Kubernetes does support Windows nodes for exactly this. In practice, though, the honest answer most teams land on is that if Docker/Kubernetes-native deployment is the goal, migrating the API to ASP.NET Core (which runs natively and lightly in Linux containers) is usually the better long-term move rather than containerizing the Framework version as-is.
Test yourself
A quick mock test covering the ground above — the rapid-fire round that often opens a classic ASP.NET Web API interview before the deeper follow-ups.
Question 1 of 12
Score: 0 / 0
1. What base class does a classic ASP.NET Web API controller inherit from?