Building RESTful APIs the Right Way in ASP.NET Core

Search for a command to run...

No comments yet. Be the first to comment.
Learn ASP.NET Core by building real-world apps, APIs, and services. This hands-on series takes you from setup to deployment with clean code, cloud integration, and practical tips—perfect for beginners and backend devs alike.
Dependency Injection (DI) isn’t just a buzzword. It’s one of the reasons ASP.NET Core apps are clean, testable, and maintainable. In this article, we’ll break down DI in the most practical way possible with code, real-world usage, and clarity. 🧠 Wh...
GraphQL gets pitched as a universal upgrade over REST, and I don't buy that framing. I've built both REST and GraphQL APIs in production, and the honest answer is that GraphQL solves specific problems
Every API is a user interface. The users just happen to be developers instead of end customers, and that distinction gets forgotten more often than it should. I've integrated more third-party APIs tha
The hardest incidents I've dealt with weren't the ones with obvious causes. They were the ones where a request slowed down somewhere across four or five services, and nobody could say exactly where, b
Early in my career, I built systems the way most of us do when we're starting out: controllers talking directly to the database, business logic scattered across services, view models doubling as domai

Entity Framework Core makes it easy to get an application working. It does not automatically make that application fast. I've spent a good chunk of my career optimizing systems where the biggest perfo
APIs are the backbone of most modern web and mobile apps, and ASP.NET Core makes building them a breeze. But doing it right means thinking beyond just returning data.
In this post, we’ll walk through building clean, RESTful APIs with ASP.NET Core that follow best practices and avoid common pitfalls.
If you don’t already have a project:
dotnet new webapi -n MyApiApp
cd MyApiApp
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private static List<Product> _products = new();
[HttpGet]
public IActionResult GetAll() => Ok(_products);
[HttpGet("{id}")]
public IActionResult GetById(int id)
{
var product = _products.FirstOrDefault(p => p.Id == id);
if (product is null) return NotFound();
return Ok(product);
}
[HttpPost]
public IActionResult Create(Product product)
{
product.Id = _products.Count + 1;
_products.Add(product);
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
}
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
}
✅ ASP.NET Core automatically validates model properties like [Required].
If your model is invalid, ApiController will return a 400 Bad Request with details — no extra code needed.
You can check explicitly like this:
if (!ModelState.IsValid)
return BadRequest(ModelState);
But often it’s not even necessary.
200 OK – when data is successfully returned201 Created – when you create a resource204 No Content – when you successfully delete or update without returning content400 Bad Request – when validation fails404 Not Found – when a resource doesn't existLet your API speak clearly and predictably.
ASP.NET Core comes with Swagger UI out of the box.
Program.cs (if not already there):builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
app.UseSwagger();
app.UseSwaggerUI();
Now hit https://localhost:5001/swagger to test your API visually!
Avoid returning full database models. Use DTOs (Data Transfer Objects):
public class ProductDto
{
public string Name { get; set; }
public decimal Price { get; set; }
}
It helps keep internal logic decoupled from API responses.
Now that you can build clean APIs, let’s talk about data persistence with Entity Framework Core — code-first, migrations, relationships, and more.
➡️ Entity Framework Core Deep Dive →
Let’s move from “working” to wow 🚀