REST API - Use EF Core to create a paged endpoint quickly

Search for a command to run...

No comments yet. Be the first to comment.
The purpose is to be able to create a multi-tenant database system where each tenant have its own database. We will see the different steps to implement this configuration Let’s go, begin with the STARTER KIT ! The database schema in code first First...

Maybe you already encounter this problem. You want to use the IHttpContextAccessor but it is not available and there is no indication to find the right package to use. To solve this situation, you just have to use the Microsoft.AspNetCore.Http.Abstra...

I previously explain how to create a custom configuration section in a web.config. But something miss if we want to do all the job. If you share the library with your favorites colleagues and the haven't the documentation, it is better to include the...

Here's a topic that's really interesting for many developers who like to organize their code a bit. Having a custom configuration section in a configuration file is the best approach when that configuration involves a business need, a connection to a...

There is often the question from my colleagues about how to do a quick paged requests on records without typing a lot of SQL code in stored procedure or in code by filtering a collection of records.
The answer for this question comes with EF Core but Entity Framework in general.
Open Visual Studio 2022
Create a new project (File / New / Project...)
Choose ASP.Net Core Web API (native AOT) to create a minimal API project

I let you named and store it wherever you want
The project is now created. Now go on the endpoint creation.
Add the nuget package Swashbuckle.AspNetCore to the project.
Change the Program method by this one below
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
var sampleTodos = new Todo[] {
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new(4, "Clean the bathroom"),
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2))),
new(6, "Buy vegetables to the grocery", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new(7, "Buy clothes for the wedding", DateOnly.FromDateTime(DateTime.Now.AddDays(15))),
new(8, "Clean the bedroom"),
new(9, "Mooing the lawn", DateOnly.FromDateTime(DateTime.Now.AddDays(2))),
new(10, "Cut the rose bushes", DateOnly.FromDateTime(DateTime.Now.AddDays(2))),
new(11, "Cut the wood to prepare the winter"),
};
var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos);
todosApi.MapGet("/{id}", (int id) => sampleTodos.FirstOrDefault(a => a.Id == id) is { } todo ? Results.Ok(todo) : Results.NotFound());
app.Run();
}
}
Now we have a little collection of records with a Swagger user-interface to display the API
In the .csproj, add the JsonSerializerIsReflectionEnabledByDefault tag to let Swagger auto-discover and serialize the objects
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
...
<PublishAot>true</PublishAot>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
</Project>
Open the launchSettings.json file in the Properties folder and change the launchUrl to swagger

{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5241",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
In the Program method, under the declared endpoints, add this line.
todosApi.MapGet("/page/{page}", (int page) => sampleTodos.Skip((page - 1) * 5).Take(5).ToArray() is { } todos ? Results.Ok(todos) : Results.NotFound() );
Wow, only this code !
Yes, let me detailed what we have done here !
We add a new endpoint answering to the URL https://<hosturl:port>/todos/page/<pageid>
We declare a new function with only the parameter page and where is role is to return the records of the requested page identifier
The body of the function, the real subject here :
sampleTodos.Skip((page - 1) * 5).Take(5).ToArray()
Here, we will consider a page will contain only 5 records
Thanks to Entity Framework we can call the function Skip() on the collection sampleTodos to avoid the selection of the X first records of the collection. X is the number of records of the previous page we want to skip.
And just after skipping the first records, we call the function Take() on the result to only get the 5 records of the page. This function will take 5 records at maximum so even a page have less records it will works.
Thank you Entity Framework 😊
Hi, I'm Yoann. I work as a full-stack developer, solution architect.
If you enjoyed this article, you might enjoy my other content, too.
Github: yblossier
LinkedIn: /in/yoannblossier
Buy Me A Coffee: A special thank you for your support 🍵
Thank you for joining me today.
Yoann