What is Web API in ASP.NET Core and Why Do We Use It?
An ASP.NET Core MVC application returns HTML pages: the server builds the page and the browser shows it. But today the same data is needed by many different clients: a React or Angular website, an Android app, an iPhone app, another company's system, a Power BI report. None of them want an HTML page. They want just the data.
That's what a Web API does.
A Web API is an application that exposes data and operations over HTTP, usually as JSON, so that any kind of client can use them. Instead of "show me the products page", a client asks "give me the list of products", and gets back data it can display or process however it likes.
A real-life example
Think of a restaurant. You (the client) don't walk into the kitchen and cook. You read the menu (the list of things you can ask for), place an order with the waiter (the API), and the waiter brings back your food (the data). You don't need to know how the kitchen works, whether it uses gas or electricity, or who the chef is. And the same kitchen can serve dine-in customers, take-away orders and delivery apps.
A Web API works the same way:
- The menu is the list of API endpoints:
GET /api/products,POST /api/orders... - The order is an HTTP request.
- The food is the HTTP response, usually JSON.
- The kitchen is your business logic and database, hidden from the client.
MVC vs Web API: what's the difference?
MVC application Web API
--------------- -------
Browser ── GET /Products ──► Server Any client ── GET /api/products ──► Server
Browser ◄── full HTML page ── Server Any client ◄── JSON data ───────── Server
<html><body><table> [{"id":1,"name":"Wireless Mouse","price":799},
<tr><td>Wireless Mouse</td>... {"id":2,"name":"Mechanical Keyboard","price":3499}]
| Point | MVC controller | Web API controller |
|---|---|---|
| Returns | HTML views (return View()) | Data: JSON or XML (return Ok(data)) |
| Base class | Controller (has view support) | ControllerBase (no view support needed) |
| Attribute | None required | [ApiController] |
| Client | A web browser showing pages | Any app: SPA, mobile, desktop, another server |
| Routing | Usually conventional ({controller}/{action}) | Attribute routing ([Route("api/[controller]")]) |
| Errors | Error page | HTTP status code + JSON error (ProblemDetails) |
In ASP.NET Core, MVC and Web API are one framework. The same project can have MVC controllers that return pages and API controllers that return JSON. (In the old ASP.NET on .NET Framework, they were two separate frameworks.)
Why do we use Web API?
- One backend, many clients. Write the business logic and database code once; the website, Android app, iOS app and partner systems all use the same API.
- Modern front ends need it. React, Angular, Vue and Blazor WebAssembly apps run in the browser and fetch their data from an API.
- Integration between systems. Payment gateways, shipping companies, SMS providers and ERP systems all communicate through APIs. Your app can offer its own API to partners in the same way.
- Separation of concerns. Front-end and back-end teams work independently, agreeing only on the API "contract": URLs, request and response shapes.
- Lightweight and fast. JSON is small compared with full HTML pages, which matters for mobile networks.
- Platform independent. Any language that can make an HTTP request can call it: JavaScript, Python, Java, Kotlin, Swift, C#.
- Scalability and microservices. Each service (orders, payments, inventory) can be a separate API that is deployed and scaled on its own.
REST: the style most Web APIs follow
Most Web APIs are REST (Representational State Transfer) APIs. REST is a set of simple rules that make APIs predictable:
- Everything is a resource with a URL. Use nouns, not verbs:
/api/products,/api/products/2,/api/customers/7/orders. - The HTTP method says what to do with the resource (see the table below).
- Stateless. Each request carries everything the server needs (for example a token). The server doesn't remember previous requests.
- Standard status codes tell the client what happened.
- Representations. The resource is sent in a format such as JSON.
HTTP methods (verbs)
| Method | Purpose | Example | Typical success code |
|---|---|---|---|
| GET | Read data | GET /api/products/2 | 200 OK |
| POST | Create a new resource | POST /api/products | 201 Created |
| PUT | Replace a whole resource | PUT /api/products/2 | 200 OK or 204 No Content |
| PATCH | Change part of a resource | PATCH /api/products/2 | 200 OK or 204 No Content |
| DELETE | Remove a resource | DELETE /api/products/2 | 204 No Content |
The next two lessons compare the methods that confuse people most: GET vs POST and PUT vs PATCH.
HTTP status codes you'll use every day
| Code | Meaning | ASP.NET Core helper |
|---|---|---|
| 200 OK | Success, with data in the body | Ok(data) |
| 201 Created | A new resource was created | CreatedAtAction(...) |
| 204 No Content | Success, nothing to return | NoContent() |
| 400 Bad Request | The request data is invalid | BadRequest() (automatic with [ApiController]) |
| 401 Unauthorized | Not logged in / no valid token | Unauthorized() |
| 403 Forbidden | Logged in, but not allowed | Forbid() |
| 404 Not Found | The resource doesn't exist | NotFound() |
| 409 Conflict | Conflicts with the current state (e.g. duplicate) | Conflict() |
| 415 Unsupported Media Type | The body format isn't accepted | Automatic |
| 500 Internal Server Error | A bug or failure on the server | Unhandled exceptions |
Building a Web API in ASP.NET Core
Let's build a small Products API for an electronics shop. You can create a new project with dotnet new webapi -n ShopApi --use-controllers, or add API controllers to an existing MVC project. All the responses shown in this lesson series were captured by running this exact API.
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(); // API controllers (no views needed)
builder.Services.AddSingleton<ProductStore>(); // our in-memory "database"
var app = builder.Build();
app.MapControllers(); // map attribute-routed controllers
app.Run();
The model
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Category { get; set; } = "";
public decimal Price { get; set; }
public int Stock { get; set; }
}
To keep the example simple, ProductStore is a small class holding a List<Product> with three sample products (a Wireless Mouse, a Mechanical Keyboard and a 27-inch Monitor). In a real project this would be a repository using Entity Framework Core or Dapper.
The API controller
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")] // base URL: /api/products
public class ProductsController : ControllerBase
{
private readonly ProductStore _store;
public ProductsController(ProductStore store) => _store = store;
// GET api/products
[HttpGet]
public IActionResult GetAll() => Ok(_store.GetAll());
// GET api/products/2
[HttpGet("{id:int}")]
public IActionResult GetById(int id)
{
var product = _store.Find(id);
return product is null ? NotFound() : Ok(product);
}
// DELETE api/products/2
[HttpDelete("{id:int}")]
public IActionResult Delete(int id) => _store.Remove(id) ? NoContent() : NotFound();
}
The POST, PUT and PATCH actions of this controller are explained in the next two lessons.
Calling the API
A GET request can be tested directly in the browser by opening http://localhost:5288/api/products:
Notice two things:
- We returned C# objects, and ASP.NET Core automatically converted them to JSON, with camelCase property names (
Namebecame"name"). - For the 404,
[ApiController]automatically produced a standard ProblemDetails JSON error, so every client gets errors in the same format.
What does [ApiController] do?
The [ApiController] attribute switches on behaviours that every good API needs:
- Automatic model validation: if the request data breaks a validation rule (
[Required],[Range]...), the action doesn't even run; the client gets a 400 Bad Request listing every error. No moreif (!ModelState.IsValid)in each action. - Binding source inference: complex types are read from the request body automatically (
[FromBody]), and simple types from the route or query string. - ProblemDetails responses for error status codes.
- Attribute routing is required, which keeps API URLs explicit.
How to test a Web API
| Tool | Good for |
|---|---|
| Browser | Quick GET requests only |
| Swagger UI / OpenAPI | Interactive documentation page where you can try every endpoint |
| Postman, Insomnia | Any request, with saved collections and environments |
.http files in Visual Studio / VS Code | Requests saved as text next to your code |
curl | Command line and scripts |
### ShopApi.http (Visual Studio / VS Code REST client)
GET http://localhost:5288/api/products/2
###
POST http://localhost:5288/api/products
Content-Type: application/json
{ "name": "USB-C Hub", "category": "Accessories", "price": 1899, "stock": 60 }
Interview questions
1. What is Web API?
A Web API is a service that exposes data and operations over HTTP, usually as JSON, so that any client (browsers, mobile apps, other servers) can use it. In ASP.NET Core it is built with controllers that inherit from ControllerBase and use [ApiController].
2. What is the difference between MVC and Web API?
MVC controllers return HTML views for browsers; Web API controllers return data (JSON/XML) for any client. In ASP.NET Core both are part of one framework: MVC controllers inherit Controller, API controllers inherit ControllerBase.
3. What is REST?
An architectural style in which resources are identified by URLs, HTTP methods describe the operation (GET, POST, PUT, PATCH, DELETE), communication is stateless, and standard status codes describe the result.
4. Why use ControllerBase instead of Controller for APIs?
Controller adds view support (View(), ViewBag, TempData) that an API doesn't need. ControllerBase has everything for APIs: Ok, NotFound, CreatedAtAction and model binding.
5. What does [ApiController] do?
It enables automatic 400 responses for invalid models, infers binding sources ([FromBody] for complex types), returns ProblemDetails for errors, and requires attribute routing.
6. What is the difference between 401 and 403?
401 Unauthorized means the client is not authenticated (no or invalid credentials). 403 Forbidden means the client is authenticated but doesn't have permission for this resource.
Summary
- A Web API exposes data and operations over HTTP, usually as JSON, for any kind of client.
- We use it so one backend can serve websites, mobile apps, SPAs and partner systems.
- REST APIs use resource URLs, HTTP methods, stateless requests and standard status codes.
- In ASP.NET Core, API controllers inherit
ControllerBase, use[ApiController]and attribute routing, and return results likeOk(),NotFound()andCreatedAtAction(). - Objects are serialized to JSON automatically, and validation errors become 400 responses automatically.
Next: GET vs POST in Web API.