Fermer

août 20, 2025

Développement d’API suralimente avec des points de terminaison rapides

Développement d’API suralimente avec des points de terminaison rapides


Les points de terminaison rapides vous permettent de créer des API Web avec une validation automatique, des performances élevées et moins de code. Dans cet article, nous comprendrons comment utiliser les points de terminaison rapides comme alternative aux approches classiques et combiner le meilleur des deux mondes lors de la création de nouvelles API Web dans ASP.NET Core.

La création d’API Web fait partie des routines de la plupart des développeurs ces jours-ci. En ce sens, il convient de réfléchir à la façon dont ce processus peut être accéléré pour augmenter la productivité et améliorer les performances sans sacrifier l’organisation et la maintenabilité. C’est dans cet esprit que le concept de «points de terminaison rapide a émergé.

Dans cet article, nous comprendrons ce que sont les points de terminaison rapides, comment les mettre en œuvre dans la pratique et voir quels avantages ils peuvent offrir par rapport à l’utilisation traditionnelle des contrôleurs dans ASP.NET Core et les API minimales modernes.

⚡️Prètement des points de terminaison rapides

Le concept de points d’extrémité rapide est lié aux approches qui cherchent à simplifier et à accélérer le développement des API, en mettant l’accent sur les performances, un couplage faible entre les composants et une meilleure organisation de code.

Les critères de terminaison rapides sont apparus comme une alternative aux approches traditionnelles pour la gestion des demandes dans les API Web, telles que les contrôleurs ASP.NET MVC et les API minimaux, cherchant à combiner les performances, l’organisation et la simplicité dans un seul modèle.

Points de terminaison rapides dans ASP.NET Core

Dans ASP.Net Core, nous avons accès à des points de terminaison rapides via la bibliothèque du même nom, disponible à https://fast-endpoids.com. Il fonctionne sous la licence MIT, ce qui signifie qu’il est open source et peut être utilisé dans des projets privés et commerciaux.

En outre, il suit le modèle de conception de demande de point de demande de demande (repl), qui préconise l’organisation claire des composants d’une API, la séparation des responsabilités et la facilité de maintenance et de lecture.

Avant l’arrivée des points de terminaison rapides, les principales façons de créer des API Web ont été les contrôleurs traditionnels et les API minimales modernes. Bien que les deux soient d’excellentes approches, ils ont quelques lacunes:

Contrôleurs: Bien qu’ils soient robustes, organisés et prêts pour pratiquement tout type de configuration, ils peuvent être excessivement verbeux pour des scénarios simples. La façon de mettre en œuvre un contrôleur à l’aide de classes et d’attributs génère souvent des frais généraux inutiles pour les API maigres, et dans certains cas, il peut rendre difficile d’avoir une approche plus axée sur les ressources et une séparation claire des responsabilités.

API minimaux: D’un autre côté, les API minimales offrent un moyen beaucoup plus simple de créer des points de terminaison, idéaux pour les services petits et rapides. Cependant, à mesure qu’ils grandissent, ils peuvent compromettre l’organisation et la maintenabilité du code. L’absence de conventions claires et le mélange de logique métier avec la définition de l’itinéraire peuvent rendre le code difficile à mettre à l’échelle et à tester.

C’est précisément dans ces limites que les critères de terminaison rapides se distinguent comme un terrain d’entente entre ces deux approches. Ils combinent le meilleur des deux mondes:

  • Performance et simplicité D’API minimaux, avec un routage direct et une structure allégée (la documentation indique que les performances sont à égalité avec un minimum d’API et est sensiblement meilleur que les contrôleurs MVC)
  • Organisation, testabilité et séparation des responsabilités des contrôleurs, permettant l’utilisation de la validation, des filtres, de l’injection de dépendance et de l’encapsulation propre à travers des classes spécialisées par point de terminaison

Le grand avantage des points de terminaison rapides est qu’ils vous permettent d’écrire du code propre, modulaire et performant sans sacrifier la clarté et l’évolutivité. Cela en fait un excellent choix pour les applications modernes qui nécessitent à la fois l’agilité et une base solide pour l’entretien à long terme.

Classement API

🛠️

Maintenant que nous avons vu ce que sont les points de terminaison rapides et quels sont leurs avantages par rapport aux approches traditionnelles, créons une application de base ASP.NET pour les implémenter dans la pratique.

En tant que scénario, imaginons que vous devez créer un système de journalisation d’activité pour l’équipe de développement. Ce système doit être simple, performant et en même temps des validations de support sans être complexes. Dans ce cas, nous pouvons utiliser des points de terminaison rapides pour créer une API qui correspond à ces exigences.

💡 Pour garder l’accent sur le sujet principal, certains détails d’implémentation ne seront pas affichés dans cet article, mais vous pouvez vérifier le code complet dans ce référentiel GitHub: Journal de travail – Code source.

Pour créer l’application de base, vous pouvez utiliser la commande ci-dessous. Ce message utilise la version 9 de .NET, qui est actuellement la dernière version stable.

dotnet new web -o WorkLog

Ensuite, pour installer les packages NuGet utilisés dans cet exemple, vous pouvez utiliser les commandes suivantes:

dotnet add package FastEndpoints
dotnet add package FluentValidation
dotnet add package FastEndpoints.Validation

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Tools

L’étape suivante consiste à créer la classe de modèle, alors créez un nouveau dossier appelé «modèles» et, à l’intérieur, ajouter la classe ci-dessous:

namespace WorkLog.Models;
public class TimeEntry
{
    public Guid Id { get; set; }
    public string UserName { get; set; } = default!;
    public string? ProjectName { get; set; }
    public DateTime Date { get; set; }
    public decimal Hours { get; set; }
    public string? Description { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

Le DbContext La classe sera utilisée pour définir les configurations de la base de données, alors créez un nouveau dossier appelé «données» et, à l’intérieur, ajoutez la classe suivante:

using Microsoft.EntityFrameworkCore;
using WorkLog.Models;

namespace WorkLog.Data;
public class WorkLogDbContext : DbContext
{
    public DbSet<TimeEntry> TimeEntries { get; set; }
    public WorkLogDbContext(DbContextOptions<WorkLogDbContext> options) : base(options) { }
}

Créer les points de terminaison

Les classes de points de terminaison contiendront les fonctionnalités de points de terminaison rapides. Pour cela, ils implémenteront le Endpoint Classe du package Fastendpoints NuGet. Le premier point de terminaison sera utilisé pour créer de nouveaux enregistrements dans la base de données, puis le récupérer, pour cela, nous créerons des classes auxiliaires pour la demande et la réponse. Alors, créez un nouveau dossier appelé «Demande» et à l’intérieur, ajoutez la classe ci-dessous:

namespace WorkLog.Requests;
public class CreateTimeEntryRequest
{
    public string? UserName { get; set; }
    public string? ProjectName { get; set; }
    public DateTime Date { get; set; }
    public decimal Hours { get; set; }
    public string? Description { get; set; }
}

Ensuite, créez un nouveau dossier appelé «réponse» et ajoutez-y les classes suivantes:

namespace WorkLog.Responses;
public class CreateTimeEntryResponse
{
    public Guid Id { get; set; }
    public string? UserName { get; set; }
    public string? ProjectName { get; set; }
    public DateTime Date { get; set; }
    public decimal Hours { get; set; }
    public string? Description { get; set; }
    public DateTime CreatedAt { get; set; }
}
namespace WorkLog.Responses;
public class GetTimeEntryResponse
{
    public Guid Id { get; set; }
    public string? UserName { get; set; }
    public string? ProjectName { get; set; }
    public DateTime Date { get; set; }
    public decimal Hours { get; set; }
    public string Description { get; set; } = default!;
    public DateTime CreatedAt { get; set; }
}

Enfin, créons la classe Endpoint. Créez un dossier appelé «points de terminaison» et, à l’intérieur, ajoutez la classe suivante:

using FastEndpoints;
using WorkLog.Data;
using WorkLog.Models;
using WorkLog.Requests;
using WorkLog.Responses;

namespace WorkLog.Endpoints;
public class CreateTimeEntryEndpoint : Endpoint<CreateTimeEntryRequest, CreateTimeEntryResponse>
{
    private readonly WorkLogDbContext _dbContext;

    public CreateTimeEntryEndpoint(WorkLogDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public override void Configure()
    {
        Post("/time-entries");
        AllowAnonymous();
        Summary(s =>
        {
            s.Summary = "Create a new time entry";
            s.Description = "Registers hours worked by a professional on a specific project.";
        });
    }

    public override async Task HandleAsync(CreateTimeEntryRequest req, CancellationToken ct)
    {
        var timeEntry = new TimeEntry
        {
            Id = Guid.NewGuid(),
            UserName = req?.UserName,
            ProjectName = req?.ProjectName,
            Date = req.Date,
            Hours = req.Hours,
            Description = req.Description,
            CreatedAt = DateTime.UtcNow
        };

        _dbContext.TimeEntries.Add(timeEntry);
        await _dbContext.SaveChangesAsync(ct);

        await SendAsync(new CreateTimeEntryResponse
        {
            Id = timeEntry.Id,
            UserName = timeEntry.UserName,
            ProjectName = timeEntry.ProjectName,
            Date = timeEntry.Date,
            Hours = timeEntry.Hours,
            Description = timeEntry.Description,
            CreatedAt = timeEntry.CreatedAt
        });
    }
}

Notez que le CreateTimeEntryEndpoint La classe représente un point de terminaison HTTP responsable de la création d’un nouvel enregistrement d’heures travaillé par un professionnel sur un projet.

La classe hérite de Endpoint<CreateTimeEntryRequest, CreateTimeEntryResponse>définissant le contrat d’entrée et de sortie de ce point de terminaison.

Le Configure() La méthode définit les paramètres principaux du point de terminaison. Nous spécifions qu’il répond aux demandes de publication HTTP sur le /time-entries route et permet un accès anonyme (sans authentification). Nous utilisons également le Summary() Méthode pour documenter l’objectif du point de terminaison, ce qui facilite la génération de documentation automatique et pour les autres développeurs.

La partie la plus importante est le HandleAsync méthode. Lorsqu’une demande est reçue, nous créons une nouvelle instance de TimeEntryremplissant ses champs avec les données de la demande. Ce nouvel enregistrement est ensuite ajouté au contexte et a persisté dans la base de données avec SaveChangesAsync.

Enfin, nous envoyons une réponse au client avec les données de temporisation nouvellement créées, encapsulées dans le CreateTimeEntryResponse.

Ensuite, toujours dans le dossier des points de terminaison, ajoutez la classe suivante, qui représente le point de terminaison pour la récupération des données:

using FastEndpoints;
using Microsoft.EntityFrameworkCore;
using WorkLog.Data;
using WorkLog.Responses;
namespace WorkLog.Endpoints;

public class GetTimeEntriesEndpoint : EndpointWithoutRequest<List<GetTimeEntryResponse>>
{
    private readonly WorkLogDbContext _db;

    public GetTimeEntriesEndpoint(WorkLogDbContext db)
    {
        _db = db;
    }

    public override void Configure()
    {
        Get("/time-entries");
        AllowAnonymous();
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        var entries = await _db.TimeEntries
            .Select(e => new GetTimeEntryResponse
            {
                Id = e.Id,
                UserName = e.UserName,
                ProjectName = e.ProjectName,
                Date = e.Date,
                Hours = e.Hours,
                Description = e.Description,
                CreatedAt = e.CreatedAt
            })
            .ToListAsync(ct);

        await SendAsync(entries);
    }
}

💡 Cette séparation entre les modèles d’entrée, d’entité et de réponse maintient l’application plus robuste, découplée et prête à évoluer. De plus, cette structure fournit une lecture claire, réduit les API à chaudières communes dans les API REST et offre une expérience plus fluide à la fois pour l’écrivain et le mainteneur du code.

Création des validateurs

Fastendpoints a une intégration avec le package FluentValidations, ce qui signifie que nous pouvons effectuer des validations sans trop d’effort. Ainsi, pour configurer les validations de notre API, créez un nouveau dossier appelé «validateurs» et, à l’intérieur, ajoutez la classe ci-dessous:

using FastEndpoints;
using FluentValidation;
using WorkLog.Requests;

namespace WorkLog.Validators;
public class CreateTimeEntryValidator : Validator<CreateTimeEntryRequest>
{
    public CreateTimeEntryValidator()
    {
        RuleFor(x => x.UserName).NotEmpty();
        RuleFor(x => x.ProjectName).NotEmpty();
        RuleFor(x => x.Date).NotEmpty().LessThanOrEqualTo(DateTime.Today);
        RuleFor(x => x.Hours).GreaterThan(0).LessThanOrEqualTo(24);
    }
}

Ici, nous créons une classe de validation pour vérifier les données d’entrée de la demande de création d’enregistrements. Notez que la classe hérite de Validatorqui est une classe de l’espace de noms Fastendpoints. De plus, il met en œuvre des méthodes de validation telles que NotEmpty()qui appartient à Fluentvalidation. De cette façon, nous avons des validations séparées et organisées pour chaque point final.

La dernière chose à faire est d’ajouter les paramètres nécessaires pour les classes créées précédemment au Program classe. Alors, remplacez le Program Code de classe avec le code ci-dessous:

using FastEndpoints;
using Microsoft.EntityFrameworkCore;
using WorkLog.Data;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<WorkLogDbContext>(options =>
    options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddFastEndpoints();

var app = builder.Build();

app.UseFastEndpoints();

app.Run();

Ici, en plus de configurer le WorkLogDbContext Classe de base de données, nous avons également ajouté la configuration des points FastendPoint via les méthodes builder.Services.AddFastEndpoints() et app.UseFastEndpoints().

Notez comment le Program La classe est propre et organisée, sans la présence de points d’extrémité, comme cela se produit lorsque nous utilisons l’approche API minimale. Maintenant nous pouvons réserver le Program Classe uniquement pour les configurations, qui est sa fonction principale 😊.

Réduisant les points de terminaison rapides

Maintenant que les implémentations sont prêtes, nous pouvons tester si les points de terminaison fonctionnent correctement. Pour ce faire, nous utiliserons Progress Telerik Fiddler partout Pour exécuter les demandes et vérifier les réponses.

Tout d’abord, nous exécuterons la route HTTP-POST: http://localhost:5011/time-entries Pour sauver un nouveau record. Cet exemple utilisera le JSON suivant:

{
    "userName": "John Davis",
    "projectName": "john.davis@example.com",
    "date": "2025-08-01",
    "hours": 6.5,
    "description": "Worked on implementing the user authentication flow and fixed bugs related to token refresh."
}

Exécution du point de terminaison rapide OK

La réponse dans Fiddler a renvoyé un statut de 200 – OKce qui signifie que le point final a fonctionné correctement.

Maintenant, exécutons le même point de terminaison, mais cette fois sans envoyer les paramètres requis pour vérifier si les validations FluentValidation fonctionnent. Cette fois, le JSON suivant sera envoyé dans le corps de la demande:

{
    "userName": "",
    "projectName": "",
    "date": "2025-08-01",
    "hours": 6.5,
    "description": "Worked on implementing the user authentication flow and fixed bugs related to token refresh."
}

Erreur de point final en cours d'exécution

Maintenant, comme prévu, la réponse a été une erreur indiquant que certains champs sont obligatoires.

Enfin, nous ferons une demande qui utilisera le GetTimeEntriesEndpoint pour récupérer l’enregistrement précédemment inséré. Donc, exécuter la route HTTP: Get – http://localhost:5011/time-entriesnous aurons le résultat suivant:

Exécution du résultat du point de terminaison rapide

📌conclusion

Fastendpoints offre un moyen moderne et polyvalent de construire des API dans ASP.NET Core, combinant les performances et la simplicité des API minimaux avec le cadre du contrôleur. Cette approche équilibrée améliore la maintenabilité et facilite l’évolutivité et la testabilité.

Dans cet article, nous explorons ses principaux avantages et créons un exemple d’API à l’aide du package NuGet, en soulignant comment sa conception centrée sur le point final se traduit par un code plus propre.

Si vous recherchez une alternative aux modèles d’API traditionnels, Fastendpoints mérite d’être exploré. En plus des fonctionnalités couvertes dans cet article, il y en a d’autres, comme la validation, les filtres et la testabilité, qui vous aideront probablement dans vos projets.




Source link