In the previous post, we created new tasks and got our backend to communicate with PostgreSQL. By including Update (PUT) and Delete (DELETE) routes, we will finish the circle today. This indicates that our small API can now perform full CRUD!
But first, a brief note before we get into the code:
π It wasn't the best idea to store PostgreSQL credentials directly in appsettings.json
, as someone noted in the previous post's comments. It's true! An environment variable (or a .env
file with something like dotnet user-secrets
or dotenv.net
) can be used instead. In this manner, you can avoid inadvertently entering your database password into GitHub.
π§ Step 1: Adding Update (PUT) Route
When we update, we take an existing task, make changes to its fields, and then save it again. That is typically a FindAsync β modify β SaveChangesAsync
pattern in EF Core.
This is how it appears in a minimalist API style:
// Update a task
app.MapPut("/api/tasks/{id}", async (AppDbContext db, int id, TodoItem updatedTask) =>
{
var toBeUpdated = await db.Tasks.FindAsync(id);
if (toBeUpdated == null) return Results.NotFound();
toBeUpdated.Title = updatedTask.Title;
toBeUpdated.IsComplete = updatedTask.IsComplete;
await db.SaveChangesAsync();
return Results.Ok(toBeUpdated);
});
π What is going on here?
- The URL (
/api/tasks/3
) is where theid
originates. -
db
is the database context that .NET injects into our database. - The request body (the updated values) is where
updatedTask
originates. - We update the task's fields, verify that it exists, and then save.
π§ Step 2: Adding the delete (DELETE) route
Deleting is even simpler:
// Delete a task
app.MapDelete("/api/tasks/{id}", async (int id, AppDbContext db) =>
{
var task = await db.Tasks.FindAsync(id);
if (task == null) return Results.NotFound();
db.Tasks.Remove(task);
await db.SaveChangesAsync();
return Results.Ok(new { message = $"Task {id} deleted" });
});
Thatβs it! If the task is found, itβs removed. Otherwise, the API returns a 404 Not Found
.
π§Step 3: Trying it our on Postman
PUT
: Send a request to http://localhost:5001/api/tasks/1
with body:
{
"title": "Write blog post",
"isComplete": true
}
DELETE
: Send a request to http://localhost:5001/api/tasks/1
.
That's it! If you've done everything as suggested, the routes will update the task with ID 1 and delete it respectively.
π± Small Improvement: Store DB Credentials in Environment Variables
Instead of in appsettings.json
:
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=todo_db;Username=postgres;Password=supersecret"
}
Use environment variables through Program.cs
(cross-platform safe):
builder.Services.AddDbContext<AppDbContext>(options => options.UseNpgsql(Environment.GetEnvironmentVariable("PG_CONNECTION")));
And in your shell:
export PG_CONNECTION="Host=localhost;Database=todo_db;Username=postgres;Password=supersecret"
This way, you wonβt leak secrets into GitHub.
ποΈ Full Codebase + Frontend
I've posted the complete codebase to GitHub, go there if you want to view it, tweak it and build it along with the React frontend that uses this API.
That way, you won't just be reading snippets.
Top comments (0)