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

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

ยท

3 min read

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.

Create the API project

  1. Open Visual Studio 2022

  2. Create a new project (File / New / Project...)

  3. Choose ASP.Net Core Web API (native AOT) to create a minimal API project

  1. I let you named and store it wherever you want

  2. The project is now created. Now go on the endpoint creation.

Create the list of records

  1. Add the nuget package Swashbuckle.AspNetCore to the project.

  2. 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();
    }
}
  1. Now we have a little collection of records with a Swagger user-interface to display the API

  2. 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>
  1. 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"
      }
    }
  }
}
  1. Launch the application

Create the endpoint for paged list of records

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 !

  1. We add a new endpoint answering to the URL https://<hosturl:port>/todos/page/<pageid>

  2. We declare a new function with only the parameter page and where is role is to return the records of the requested page identifier

  3. 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 ๐Ÿ˜Š

  1. Launch the application and try yourself with the new endpoint.

Let's Connect!

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

ย