Introduction: REST API in C# is Simple
Creating a modern REST API in C# using ASP.NET Core is one of the most in-demand tasks in backend development. Many beginner developers think that writing a full-fledged API requires weeks of preparation. In reality, using the right tools, you can create a working REST API in C# in literally 30 minutes.
In this article, we will practically break down how to write a REST API in C# from scratch. We will create a simple microservice for managing a task list (Todo List) using the built-in capabilities of ASP.NET Core. You will learn how to set up routing, implement CRUD operations, and test the API via Swagger UI.
1. Project Setup in 5 Minutes
First, make sure you have .NET SDK 6.0 or newer installed. If not, download it from the official Microsoft website. Open a terminal and run the following commands:
dotnet new webapi -n TodoApicd TodoApicode .These commands will create a new Web API project and open it in Visual Studio Code. The project structure includes several important files:
Program.cs— entry point and service configurationControllers/— folder for API controllersappsettings.json— configuration file
By default, the project already contains an example controller WeatherForecastController. We will delete it and create our own.
Important: Make sure the Program.cs file contains the lines builder.Services.AddControllers(); and app.MapControllers();. This is the standard configuration for a REST API in C#.
2. Creating the Data Model and Controller (10 Minutes)
Let's start by creating a data model. In the project root folder, create a Models folder and add a TodoItem.cs file to it:
public class TodoItem{ public int Id { get; set; } public string Title { get; set; } = string.Empty; public bool IsComplete { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow;}Now let's create the controller. In the Controllers folder, add a TodoController.cs file. This is the heart of our REST API in C#:
[ApiController][Route("api/[controller]")]public class TodoController : ControllerBase{ private static List<TodoItem> _todos = new(); private static int _nextId = 1;
[HttpGet] public IActionResult GetAll() { return Ok(_todos); }
[HttpGet("{id}")] public IActionResult GetById(int id) { var todo = _todos.FirstOrDefault(t => t.Id == id); if (todo == null) return NotFound(); return Ok(todo); }
[HttpPost] public IActionResult Create(TodoItem item) { item.Id = _nextId++; _todos.Add(item); return CreatedAtAction(nameof(GetById), new { id = item.Id }, item); }
[HttpPut("{id}")] public IActionResult Update(int id, TodoItem item) { var existing = _todos.FirstOrDefault(t => t.Id == id); if (existing == null) return NotFound(); existing.Title = item.Title; existing.IsComplete = item.IsComplete; return NoContent(); }
[HttpDelete("{id}")] public IActionResult Delete(int id) { var todo = _todos.FirstOrDefault(t => t.Id == id); if (todo == null) return NotFound(); _todos.Remove(todo); return NoContent(); }}Pay attention to the attributes:
[ApiController]— enables automatic model validation[Route("api/[controller]")]— sets the base route/api/todo[HttpGet], [HttpPost], [HttpPut], [HttpDelete]— bind