Continuing the topic, I want to give a complete example of minimal APIs in Blazor with Entity Framework Core with complex objects.I always struggle to have a solution working when my model has dependencies with other object. Here I show my test and my code. The code is in NET9. In the Microsoft documentation, there are some examples, but it is not complex enough. A few days ago, I posted about another problem I had with NET9 and Entity Framework Core.
The full source code of this post is available on GitHub. If you have any questions, please comment below or post in the forum.
The complete code is spanned through those posts:
- APIs with Entity Framework Core
- APIs with Entity Framework Core: POST
- APIs with Entity Framework Core: PUT
Send the first POST request
In my previous post, I prepared the minimal APIs using the Scaffolded Item tool in Visual Studio. Also, Swagger was added to the project. Now, I want to submit a json to create a new Client
record. Then, open Swagger and under the Clients
section. Now, I have to use the POST verb to send a valid json
with all the details.
This is a valid json
to use in order to create a new record.
{
"firstname": "Test1",
"lastname": "Test2",
"channels": [
{
"Id": 1,
"name": "Google"
},
{
"Id": 2,
"name": "Bing"
}
]
}
As a reminder, I have created the 2 records for the Channels
. Now, when I submit this request, the code raises an error because the 2 entities for the channel already exist in the database.
The initial code
So, in order to avoid this error, the strategy is to ready the channels from the database and add them to the object. The code generated by Visual Studio was this one:
group.MapPost("/", async(Domain.Client client, MyDbContext db) =>
{
db.Clients.Add(client);
await db.SaveChangesAsync();
return TypedResults.Created($"/api/Client/{client.Id}", client);
})
.WithName("CreateClient")
.WithOpenApi();
That means the POST verb receives in the variable client
the json object. Then, it is translated to the Client
model. When I add this object to the database using db.Clients.Add(client);
the record for the channels that already exist. So, Entity Framework raises an error because I can’t add to the database those values.
After saving in the database successfully, the API returns an HTTP Created 201.
The fix
As I said before, what I have to do is to replace the channels in the Client
model with the data from the database. Here is the code.
group.MapPost("/", async (Domain.Client client, MyDbContext db) =>
{
if (client.Channels != null && client.Channels.Count > 0)
{
var list = client.Channels;
client.Channels = new List<Channel>();
foreach (var c in list)
{
var channel = await db.Channels.FirstOrDefaultAsync(ch => ch.Id == c.Id);
if (channel != null)
client.Channels.Add(channel);
}
}
db.Clients.Add(client);
await db.SaveChangesAsync();
return TypedResults.Created($"/api/Client/{client.Id}", client);
})
.WithName("CreateClient")
.WithOpenApi();
What is new here? The lines are retrieving the data from the database and adding the object (if exists) to the Client
object. Now, I run again the creation of the record using Swagger and it is working.
The result
Therefore, the result is that in the database I see the records in the Clients
table as in the json
.

Also, I see that in the ChannelClient
table, there are records for a Client
Id with the related ChannelsId
.

POST APIs with Entity Framework Core video
Now, to help you and as a future reference, I created a video with this code. Please, click on it and subscribe to my YouTube channel.
Retrieve the data with GET
At this point, I have a nice POST that saves a Client
object with its dependencies. What if I want to retrieve this Client
with the dependencies using the APIs?
For that, the GET implementation is what I need. The initial implementation doesn’t include the Channel
details. For that, I have to change the function that returns the Client
object by Id. The code is the following:
group.MapGet("/{id}", async Task<Results<Ok<Domain.Client>, NotFound>>
(long id, MyDbContext db) =>
{
return await db.Clients.AsNoTracking()
.Include(c => c.Channels)
.FirstOrDefaultAsync(model => model.Id == id)
is Domain.Client model
? TypedResults.Ok(model)
: TypedResults.NotFound();
})
.WithName("GetClientById")
.WithOpenApi();
The only change in this code from the one generated by Visual Studio is that I added the include
to ask Entity Framework Core to consider the linked Channels
table. The result is the full Client
object.

Wrap up
In conclusion, in this post I show how to change the minimal APIs with Entity Framework Core and fix the POST. Also, I updated the GET method to return the full Client
object. But this is not the end. Look for the next post.
Happy coding!