In this guide, we'll build a simple ASP.NET Core Web API with a controller, connected to a PostgreSQL database — all using Visual Studio Code.
🧰 Prerequisites
Make sure you have the following installed:
- Visual Studio Code
- C# Dev Kit extension for VS Code
- .NET 9 SDK
- PostgreSQL (running locally or in Docker)
🚀 Create a New API Project
Open your terminal and run:
dotnet new webapi --use-controllers -o TodoApi
cd TodoApi
code -r .
This creates a new ASP.NET Core Web API project and opens it in VS Code.
🧩 Add Swagger for API Docs
Add the NSwag.AspNetCore package to enable OpenAPI (Swagger UI):
dotnet add package NSwag.AspNetCore
Then, open Program.cs and update it like this:
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwaggerUi(options =>
{
options.DocumentPath = "/openapi/v1.json";
});
}
Now when you run the app, you’ll have an interactive API UI at: 👉 https://localhost:5001/swagger
🧱 Create the Model
Create a folder named Models, and inside it, add TodoItem.cs:
namespace TodoApi.Models;
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
This class represents a single "to-do" item in your database.
🗄️ Add Entity Framework Core
Entity Framework Core (EF Core) lets us interact with a database using C# models.
Install EF Core:
dotnet add package Microsoft.EntityFrameworkCore --version 9.0.10
We’ll use PostgreSQL, so add the provider packages:
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL.Design
dotnet add package Microsoft.EntityFrameworkCore.Tools
🔗 Configure the Database Connection
Open appsettings.json and add your connection string:
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Port=5432;Database=CSharpCornerDB;Username=yourusername;Password=yourpassword"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
🧩 Create the Database Context
Add a Data folder and inside it, create TodoContext.cs:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Data;
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
public DbSet<TodoItem> TodoItems => Set<TodoItem>();
}
Then register the context in Program.cs:
using Microsoft.EntityFrameworkCore;
using TodoApi.Data;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<TodoContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
var app = builder.Build();
🧠 Create the Controller
Add a folder named Controllers and create a file called TodoItemsController.cs:
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;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
=> await _context.TodoItems.ToListAsync();
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var item = await _context.TodoItems.FindAsync(id);
if (item == null) return NotFound();
return item;
}
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
_context.TodoItems.Add(item);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
}
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
if (id != item.Id) return BadRequest();
_context.Entry(item).State = EntityState.Modified;
await _context.SaveChangesAsync();
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
var item = await _context.TodoItems.FindAsync(id);
if (item == null) return NotFound();
_context.TodoItems.Remove(item);
await _context.SaveChangesAsync();
return NoContent();
}
}
🧩 Apply Migrations and Update Database
Initialize EF migrations:
dotnet ef migrations add InitialCreate
dotnet ef database update
This creates the database schema in PostgreSQL.
▶️ Run the API
Finally, run the app:
dotnet run
Visit /swagger to explore and test your API endpoints.
🎉 Done!
You now have a working ASP.NET Core 9 Web API connected to PostgreSQL, with full CRUD operations and Swagger documentation — built entirely from Visual Studio Code.
Happy coding! 🧑💻