How to Write a REST API in C# in 30 Minutes: A Step-by-Step Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: REST API in C# — It's Simple



REST API (Representational State Transfer) is an architectural style that allows clients and servers to exchange data via HTTP. In modern web development, API is the de facto standard for creating backends for mobile applications, websites, and microservices. On the .NET platform (C#), REST API development is highly optimized: you can get a working prototype literally in half an hour, even if you are a beginner.



In this article, we will create a full-fledged REST API for managing a ToDo List. You will learn how to set up an ASP.NET Core Web API project, create a data model, implement CRUD operations (Create, Read, Update, Delete), and test the API via Swagger. The entire process will take no more than 30 minutes.



1. Creating the Project and Installing Dependencies



First, open Visual Studio 2022 (or Visual Studio Code with .NET SDK 6.0/7.0/8.0 installed). Follow these steps:



  1. Select Create a new project → ASP.NET Core Web API.
  2. Name the project, for example TodoApi.
  3. Make sure the framework .NET 8.0 (or higher) is selected.
  4. Uncheck Use controllers if you want to use minimal API, but in this tutorial we will use classic controllers — leave it checked.
  5. Click Create.


After creating the project, the structure will look like this:



TodoApi/├── Controllers/├── Models/├── Program.cs└── appsettings.json


No additional packages need to be installed — all necessary components are already built into ASP.NET Core.



2. Creating the Data Model and Database Context



2.1. TodoItem Model



Create a Models folder and add the TodoItem.cs class to it:



namespace TodoApi.Models;

public class TodoItem{ public int Id { get; set; } public string? Title { get; set; } public bool IsComplete { get; set; }}


This is a minimal model: an identifier, a task title, and a completion flag.



2.2. Database Context



Now let's create a context for Entity Framework Core. In the Data folder (create it), add the TodoContext.cs class:



using Microsoft.EntityFrameworkCore;using TodoApi.Models;

namespace TodoApi.Data;

public class TodoContext : DbContext{ public TodoContext(DbContextOptions<TodoContext> options) : base(options) { }

public DbSet<TodoItem> TodoItems { get; set; }}


2.3. Configuring Program.cs



Open Program.cs and add the context registration and Swagger:



using Microsoft.EntityFrameworkCore;using TodoApi.Data;

var builder = WebApplication.CreateBuilder(args);

// Add controllersbuilder.Services.AddControllers();

// Register the DB context (using InMemory for simplicity)builder.Services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));

// Swaggerbuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment()){ app.UseSwagger(); app.UseSwaggerUI();}

app.UseHttpsRedirection();app.UseAuthorization();app.MapControllers();

app.Run();


Note: we are using UseInMemoryDatabase — this is convenient for prototyping. In a real project, replace it with SQL Server, PostgreSQL, or another database.



3. Implementing the Controller with CRUD Operations



Now for the most important part — the controller. Create a file TodoItemsController.cs in the Controllers folder:



using Microsoft.AspNetCore.Mvc;using Microsoft.EntityFrameworkCore;using TodoApi.Data;using TodoApi.Models;

namespace TodoApi.Controllers;

[Route("api/[controller]")][ApiController]public class TodoItemsController : ControllerBase{ private readonly TodoContext _context;

public TodoItemsController(TodoContext context) { _context = context; }

// GET: api/TodoItems [HttpGet] public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() { return await _context.TodoItems.ToListAsync(); }

// GET: api/TodoItems/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(int id) { var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null) { return NotFound(); }

return todoItem; }

// POST: api/TodoItems [HttpPost] public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync();

return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); }

// PUT: api/TodoItems/5 [HttpPut("{id}")] public async Task<IActionResult> PutTodoItem(int id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); }

_context.Entry(todoItem).State = EntityState.Modified;

try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } }

return NoContent(); }

// DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task<IActionResult> DeleteTodoItem(int id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); }

_context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync();

return NoContent(); }

private bool TodoItemExists(int id) { return _context.TodoItems.Any(e => e.Id == id); }}

Blogs

Book Recommendations