DotNet Help

CRUD Operations

We will now proceed to write CRUD operations for an Event API. The aim is to Create, Read, Update, and Delete. Once we have these foundations, it will be much easier to grasp more concepts.

Just after builder.Build(); you should have the following source code:

//create an event app.MapPost("/event", async (Event newEvent, AppDbContext db) => { db.Events.Add(newEvent); await db.SaveChangesAsync(); return Results.Created($"/event/{newEvent.Id}", newEvent); }); //get all events app.MapGet("/events", async(AppDbContext db) => await db.Events.ToListAsync()); //get event by id app.MapGet("/event/{id}", async (int id, AppDbContext db) => await db.Events.FindAsync(id) is Event @event ? Results.Ok(@event) : Results.NotFound()); //update an event app.MapPut("/event/{id}", async (int id, Event inputEvent, AppDbContext db) => { var @event = await db.Events.FindAsync(id); if (@event is null) return Results.NotFound(); @event.Title = inputEvent.Title; @event.Description = inputEvent.Description; @event.Capacity = inputEvent.Capacity; @event.StartTime = inputEvent.StartTime; @event.EndTime = inputEvent.EndTime; await db.SaveChangesAsync(); return Results.NoContent(); }); //delete an event app.MapDelete("/event/{id}", async (int id, AppDbContext db) => { if (await db.Events.FindAsync(id) is null) { return Results.NotFound(); } else if (await db.Events.FindAsync(id) is Event @event) { db.Remove(@event); await db.SaveChangesAsync(); return Results.NoContent(); } return Results.NoContent(); });

The last line of code should be app.Run();

Code Breakdown

Let's break down the source code for better understanding:

1. Create Event

//create an event app.MapPost("/event", async (Event newEvent, AppDbContext db) => { db.Events.Add(newEvent); await db.SaveChangesAsync(); return Results.Created($"/event/{newEvent.Id}", newEvent); });

This route handles HTTP POST requests sent to /event. Its purpose is to create and save a new event in the in-memory database.

Code

Explanation

app.MapPost("/event")

/event is the path where the clients send the event data

(Event newEvent, AppDbContext db)

Two parameters are injected: the event data from the request body i.e., Postman or REST Client (newEvent) and AppDbContext from the service container (db)

db.Events.Add(newEvent)

Adds the new event to the in-memory database's Events Collection

await db.SaveChangesAsync();

Saves changes to the database asynchronously (non-blocking)

return Results.Created($"/event/{newEvent.Id}", newEvent)

Returns an HTTP 201 Created response with the newly created event and its URL

Testing with REST Client now

The scaffolded project comes with REST Client which is used to test the endpoints of the application.

To generate the endpoints without needing to do them manually:

  1. Hold Ctrl + Q on your keyboard and search for "Endpoint Explorer"

  2. It will give you all the available endpoints

  3. Right-click on the POST request and generate the request

On the generated endpoint, add the following data for testing:

{ "title": "JS hackathon", "description": "Networking and talks", "startTime": "2025-09-10T09:00:00", "endTime": "2025-09-10T17:00:00", "capacity": 150 }
1753185753966.png

2. Get All Events

//get all events app.MapGet("/events", async(AppDbContext db) => await db.Events.ToListAsync());

What This Does:

This route handles HTTP GET requests sent to /events. It retrieves a list of all events stored in the in-memory database.

Code

Explanation

app.MapGet("/events")

Route to the path /events

AppDbContext db

Injects AppDbContext via dependency injection to interact with the database

await db.Events.ToListAsync()

Asynchronously fetches all event records from the Events table and returns them as a list

Testing with REST Client

  1. Hold Ctrl + Q on your keyboard and search for "Endpoint Explorer"

  2. It will give you all the available endpoints

  3. Right-click on the GET request and generate the request

On the generated endpoint, add a valid endpoint:

GET {{0.EventApi_HostAddress}}/events

3. Get an Event by ID

//get event by id app.MapGet("/event/{id}", async (int id, AppDbContext db) => await db.Events.FindAsync(id) is Event @event ? Results.Ok(@event) : Results.NotFound());

What This Does:

This route handles HTTP GET requests sent to /event/ . It looks up a single event using the provided id from the database. If the event exists, it returns the event data; if not, it returns a "Not Found" response.

code

Explanation

app.MapGet("/event/")

route a GET with dynamic id in the url path i.e /event/3

(int id, AppDbContext db)

The route handler takes the id from the URL and usesDependency Injection to get the AppDbContext.

await db.Events.FindAsync(id)

Looks for the event with the matching id in the database. Returns null if not found.

is Event @event ? Results.Ok(@event) : Results.NotFound())

If the event exists, returns a 200 OK response with the event. If it doesn’t, returns 404 Not Found.

Testing with REST Client (Get by ID)

  1. Hold Ctrl + Q on your keyboard and search for "Endpoint Explorer"

  2. It will give you all the available endpoints

  3. Right-click on the GET{id} request and generate the request

On the generated endpoint, add a valid id

GET {{0.EventApi_HostAddress}}/event/4

4. Update an Event

//update an event app.MapPut("/event/{id}", async (int id, Event inputEvent, AppDbContext db) => { var @event = await db.Events.FindAsync(id); if (@event is null) return Results.NotFound(); @event.Title = inputEvent.Title; @event.Description = inputEvent.Description; @event.Capacity = inputEvent.Capacity; @event.StartTime = inputEvent.StartTime; @event.EndTime = inputEvent.EndTime; await db.SaveChangesAsync(); return Results.NoContent(); });

What This Does:

This route handles HTTP PUT requests to update an existing event in the database. The client provides an updated version of the event, and if the event exists, its values are modified and saved.

Code

Explanation

MapPut("event/{id}")

Sets up a PUT route for updating an event by ID

(int id, Event inputEvent, AppDbContext db)

The route handler receives the event id from the URL, the updated event data from the request body, and a database context via Dependency Injection

await db.Events.FindAsync(id)

Tries to find the event in the database using the provided id

if (@event is null) return Results.NotFound()

If no event is found, it returns a 404 Not Found response

@event.Title = inputEvent.Title ...and the rest

Updates each field of the found event with the new values provided

await db.SaveChangesAsync()

Commits the changes to the database

return Results.NoContent()

Returns a 204 No Content response to indicate the update was successful, but there's nothing to return in the body

Testing with REST Client (Update)

  1. Hold Ctrl + Q on your keyboard and search for "Endpoint Explorer"

  2. It will give you all the available endpoints

  3. Right-click on the UPDATE request and generate the request

On the generated endpoint, add the following data for testing:

{ "id": 1, "title": "Annual Meetup - Updated", "description": "Networking, and workshops", "startTime": "2025-09-10T09:00:00", "endTime": "2025-09-10T18:00:00", "capacity": 245 }

5. Delete an Event

//delete an event app.MapDelete("/event/{id}", async (int id, AppDbContext db) => { if (await db.Events.FindAsync(id) is null) { return Results.NotFound(); } else if (await db.Events.FindAsync(id) is Event @event) { db.Remove(@event); await db.SaveChangesAsync(); return Results.NoContent(); } return Results.NoContent(); });

What This Does:

This endpoint handles HTTP DELETE requests to remove an event from the database by its ID. It first checks if the event exists and deletes it if found.

Code

Explanation

app.MapDelete("/event/{id}")

Sets up a DELETE route for removing an event by ID

(int id, AppDbContext db)

The handler receives the event id from the URL and uses the injected database context db

if (await db.Events.FindAsync(id) is null)

Checks if the event exists. If not, returns 404 Not Found

else if (await db.Events.FindAsync(id) is Event @event)

Retrieves the event again and stores it in @event

db.Remove(@event)

Marks the event for deletion

await db.SaveChangesAsync()

Commits the deletion to the database

return Results.NoContent()

Returns a 204 No Content response indicating successful deletion

Testing with REST Client (Delete)

  1. Hold Ctrl + Q on your keyboard and search for "Endpoint Explorer"

  2. It will give you all the available endpoints

  3. Right-click on the DELETE request and generate the request

On the generated endpoint, add a valid id:

DELETE {{0.EventApi_HostAddress}}/event/5

MapGroup API

You will realize that events URL prefix repeats itself. That is what we should fix with MapGroup method which help us to organize such groups to avoid it being repeated.

Replace Program.cs with the following:

using _0.EventApi.Models; using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase("EventDb")); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); var app = builder.Build(); //MapGroup API var events = app.MapGroup("/events"); //create an event events.MapPost("/", async (Event newEvent, AppDbContext db) => { db.Events.Add(newEvent); await db.SaveChangesAsync(); return Results.Created($"/event/{newEvent.Id}", newEvent); }); //get all events events.MapGet("/", async(AppDbContext db) => await db.Events.ToListAsync()); //get event by id events.MapGet("/{id}", async (int id, AppDbContext db) => await db.Events.FindAsync(id) is Event @event ? Results.Ok(@event) : Results.NotFound()); //update an event events.MapPut("/{id}", async (int id, Event inputEvent, AppDbContext db) => { var @event = await db.Events.FindAsync(id); if (@event is null) return Results.NotFound(); @event.Title = inputEvent.Title; @event.Description = inputEvent.Description; @event.Capacity = inputEvent.Capacity; @event.StartTime = inputEvent.StartTime; @event.EndTime = inputEvent.EndTime; await db.SaveChangesAsync(); return Results.NoContent(); }); //delete an event events.MapDelete("/{id}", async (int id, AppDbContext db) => { if (await db.Events.FindAsync(id) is null) { return Results.NotFound(); } else if (await db.Events.FindAsync(id) is Event @event) { db.Remove(@event); await db.SaveChangesAsync(); return Results.NoContent(); } return Results.NoContent(); }); app.Run();

Breakdown:

  • var events = app.MapGroup("/events"); - to set up the group using the URL prefix /events.

  • Changes all the app.Map<HttpVerb> methods to todoItems.Map<HttpVerb>.

07 August 2025