De la configuration initiale du projet à l'aide de .NET CLI à la configuration du middleware, des contrôleurs et des services, découvrez chaque étape pour créer une API robuste. Découvrez les meilleures pratiques en matière d'injection de dépendances, d'actions asynchrones et de gestion des exceptions pour créer des applications Web évolutives et efficaces.
Utilisez la CLI .NET pour créer un nouveau projet d'API Web. Cela définit une structure de projet de base comprenant Program.cs pour le démarrage et un contrôleur WeatherForecast à titre d'exemple.
dotnet new webapi -n MyWebApi
.NET 8 poursuit la tendance vers des API minimales, vous permettant de configurer les services et les points de terminaison de manière simplifiée et concise directement dans le fichier Program.cs.
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello, World!"); app.Run();
Les contrôleurs gèrent les requêtes HTTP entrantes et répondent au client. Ils sont définis en héritant de ControllerBase et en annotant avec [ApiController].
[ApiController] [Route("[controller]")] public class MyController : ControllerBase { [HttpGet] public IActionResult Get() => Ok("Hello from MyController"); }
L’injection de dépendances (DI) intégrée de .NET Core facilite la gestion des dépendances. Vous pouvez injecter des services dans vos contrôleurs via leurs constructeurs.
public class MyService { public string GetMessage() => "Injected message"; } public class MyController : ControllerBase { private readonly MyService _myService; public MyController(MyService myService) { _myService = myService; } [HttpGet] public IActionResult Get() => Ok(_myService.GetMessage()); }
Les services (comme les contextes de base de données, les services personnalisés, etc.) sont configurés dans le fichier Program.cs, ce qui les rend disponibles pour l'injection de dépendances dans toute votre application.
builder.Services.AddScoped<MyService>();
.NET prend en charge les fichiers de configuration spécifiques à l'environnement (appsettings.json, appsettings.Development.json, etc.), permettant différents paramètres en fonction de l'environnement de l'application.
// appsettings.Development.json { "Logging": { "LogLevel": { "Default": "Debug" } } }
Les composants middleware forment un pipeline qui gère les demandes et les réponses. Un middleware personnalisé peut être créé pour des problèmes transversaux tels que la journalisation ou la gestion des erreurs.
app.Use(async (context, next) => { // Custom logic before passing to the next middleware await next(); // Custom logic after executing the next middleware });
Le routage dans l'API Web .NET est réalisé via le routage d'attributs sur les contrôleurs et les méthodes d'action. Cela permet aux URL d'être mappées directement aux actions du contrôleur.
[HttpGet("myaction/{id}")] public IActionResult GetAction(int id) => Ok($"Action with ID = {id}");
La liaison de modèle mappe automatiquement les données des requêtes HTTP aux paramètres de la méthode d'action. Il prend en charge les types complexes, notamment les corps JSON et les paramètres de chaîne de requête.
public class MyModel { public int Id { get; set; } public string Name { get; set; } } [HttpPost] public IActionResult PostAction([FromBody] MyModel model) => Ok(model);
Les annotations de données peuvent être utilisées pour valider les données du modèle. L'attribut [ApiController] applique automatiquement la validation, répondant par 400 si le modèle n'est pas valide.
public class MyModel { [Required] public int Id { get; set; } [StringLength(100)] public string Name { get; set; } }
Les actions asynchrones améliorent l'évolutivité en libérant des threads en attendant la fin des opérations d'E/S. Utilisez le mot clé async et renvoyez Task ou Task<IActionResult>.
[HttpGet("{id}")] public async Task<IActionResult> GetAsync(int id) { var result = await _service.GetByIdAsync(id); return Ok(result); }
La gestion globale des exceptions permet un traitement centralisé des erreurs, une journalisation et des réponses API standardisées sur les exceptions non gérées.
app.UseExceptionHandler(a => a.Run(async context => { var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>(); var exception = exceptionHandlerPathFeature.Error; // Log the exception, generate a custom response, etc. context.Response.StatusCode = 500; await context.Response.WriteAsJsonAsync(new { Error = "An unexpected error occurred" }); }));
La gestion des versions de l'API permet de gérer les modifications apportées à l'API au fil du temps. La plate-forme .NET prend en charge la gestion des versions via une chaîne de requête, un chemin d'URL ou un en-tête de requête.
builder.Services.AddApiVersioning(options => { options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = new ApiVersion(1, 0); options.ReportApiVersions = true; });
La négociation de contenu permet à une API de servir différents formats de réponse en fonction de l'en-tête Accept de la demande, permettant ainsi la prise en charge de formats tels que JSON, XML, etc.
builder.Services.AddControllers() .AddXmlDataContractSerializerFormatters();
Personnalisez le formatage des réponses JSON, comme la dénomination camelCase ou l'ignorance des valeurs nulles, en configurant les paramètres du sérialiseur JSON.
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.JsonSerializerOptions.IgnoreNullValues = true; });
Le partage de ressources cross-origine (CORS) permet à votre API d'être appelée à partir d'applications Web hébergées sur différents domaines. Configurez la stratégie CORS selon vos besoins.
builder.Services.AddCors(options => { options.AddPolicy("AllowSpecificOrigin", builder => builder.WithOrigins("http://example.com")); }); app.UseCors("AllowSpecificOrigin");
Sécurisez votre API en activant l'authentification, qui vérifie l'identité des utilisateurs ou des services effectuant des demandes.
builder.Services.AddAuthentication("Bearer") .AddJwtBearer(options => { options.Authority = "https://your-auth-server"; options.Audience = "your-api"; });
Après l'authentification, l'autorisation détermine si un utilisateur authentifié est autorisé à effectuer une action ou à accéder à une ressource.
[Authorize] public class SecureController : ControllerBase { // Action methods here }
Swagger (OpenAPI) fournit une documentation interactive pour votre API, permettant aux développeurs de la comprendre et de l'utiliser facilement.
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); app.UseSwagger(); app.UseSwaggerUI();
.NET Core fournit une infrastructure de journalisation intégrée qui peut enregistrer les messages sur diverses sorties (console, fenêtre de débogage, services externes, etc.).
logger.LogInformation("This is an informational message"); app.Use(async (context, next) => { logger.LogError("This is an error message before the next middleware"); await next.Invoke(); // Log after calling the next middleware });
Entity Framework Core est un ORM utilisé pour l'accès aux données dans les applications .NET. Il vous permet d'interroger et de manipuler des données à l'aide d'objets fortement typés.
public class MyDbContext : DbContext { public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) {} public DbSet<MyModel> MyModels { get; set; } }
Les migrations vous permettent d'appliquer un contrôle de version à votre schéma de base de données en suivant les modifications apportées à vos modèles de données.
dotnet ef migrations add InitialCreate dotnet ef database update
Le modèle Repository fait abstraction de la couche de données, rendant votre application plus modulaire et plus facile à maintenir.
public interface IRepository<T> { Task<IEnumerable<T>> GetAllAsync(); Task<T> GetByIdAsync(int id); // Other methods... } public class MyRepository<T> : IRepository<T> where T : class { private readonly MyDbContext _context; public MyRepository(MyDbContext context) { _context = context; } // Implement methods... }
Les tests unitaires garantissent le bon fonctionnement de votre API Web en testant des unités de code individuelles de manière isolée.
public class MyControllerTests { [Fact] public async Task Get_ReturnsExpectedValue() { // Arrange var serviceMock = new Mock<IMyService>(); serviceMock.Setup(service => service.GetAsync()).ReturnsAsync("test"); var controller = new MyController(serviceMock.Object); // Act var result = await controller.Get(); // Assert Assert.Equal("test", result.Value); } }
L'API Web .NET peut servir de backend pour une application frontale, fournissant des services RESTful.
fetch('https://localhost:5001/mycontroller') .then(response => response.json()) .then(data => console.log(data));
Les vérifications de l'état fournissent un moyen de surveiller l'état de votre application et de ses dépendances, ce qui est utile pour les architectures de microservices.
builder.Services.AddHealthChecks(); app.MapHealthChecks("/health");
SignalR active la fonctionnalité Web en temps réel, permettant au code côté serveur d'envoyer des notifications asynchrones aux applications Web côté client.
public class MyHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } }
La mise en cache des réponses réduit le nombre de requêtes qu'un serveur doit traiter en stockant une copie des ressources précédemment demandées.
[HttpGet("{id}")] [ResponseCache(Duration = 60)] public IActionResult GetById(int id) { // Retrieve and return your resource }
Servir des fichiers statiques (HTML, CSS, JavaScript, etc.) est essentiel pour soutenir les applications frontales avec une API Web .NET.
app.UseStaticFiles(); // Enable static file serving
Le modèle d'options utilise des classes pour représenter des groupes de paramètres associés. À l’aide de IOptions<T>, vous pouvez accéder à ces paramètres n’importe où dans votre application.
public class MySettings { public string Setting1 { get; set; } // Other settings } builder.Services.Configure<MySettings>(builder.Configuration.GetSection("MySettings")); public class MyService { private readonly MySettings _settings; public MyService(IOptions<MySettings> settings) { _settings = settings.Value; } // Use _settings.Setting1 }
Le middleware est un logiciel assemblé dans un pipeline d'applications pour gérer les demandes et les réponses. Un middleware personnalisé peut être créé pour effectuer des tâches spécifiques.
public class MyCustomMiddleware { private readonly RequestDelegate _next; public MyCustomMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext httpContext) { // Pre-processing logic here await _next(httpContext); // Call the next middleware in the pipeline // Post-processing logic here } } // Extension method for easy middleware registration public static class MyCustomMiddlewareExtensions { public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder builder) { return builder.UseMiddleware<MyCustomMiddleware>(); } }
La limitation de débit protège votre API contre une utilisation excessive en limitant la fréquence à laquelle un utilisateur peut effectuer des requêtes dans un certain laps de temps.
// Assume using a third-party library like AspNetCoreRateLimit builder.Services.AddInMemoryRateLimiting(); builder.Services.Configure<IpRateLimitOptions>(options => { options.GeneralRules = new List<RateLimitRule> { new RateLimitRule { Endpoint = "*", Limit = 100, Period = "1h" } }; });
Les clés API constituent un moyen simple d'authentifier et d'autoriser les appels API. Ils sont transmis du client au serveur soit dans la chaîne de requête, soit dans l'en-tête.
public class ApiKeyMiddleware { private readonly RequestDelegate _next; private const string APIKEYNAME = "x-api-key"; public ApiKeyMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { if (!context.Request.Headers.TryGetValue(APIKEYNAME, out var extractedApiKey)) { context.Response.StatusCode = 401; await context.Response.WriteAsync("API Key was not provided."); return; } // Validate the extracted API Key here... await _next(context); } }
La mise en cache de sortie vous permet de stocker la réponse à une requête. Les requêtes ultérieures peuvent être traitées à partir du cache, améliorant considérablement les performances.
[HttpGet] [ResponseCache(Duration = 120, Location = ResponseCacheLocation.Client, NoStore = false)] public IActionResult Get() { // Your logic here }
Les tâches en arrière-plan permettent aux opérations de s'exécuter en arrière-plan, indépendamment des demandes des utilisateurs, comme l'envoi d'e-mails ou le traitement de tâches de longue durée.
public class MyBackgroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // Your background task logic here await Task.Delay(TimeSpan.FromHours(1), stoppingToken); } } }
Les WebSockets fournissent un canal de communication full-duplex sur une connexion unique et longue durée, idéal pour les applications en temps réel.
app.UseWebSockets(); app.Use(async (context, next) => { if (context.WebSockets.IsWebSocketRequest) { WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); // Handle the WebSocket request here } else { await next(); } });
La localisation des demandes permet de localiser le contenu pour différentes cultures et langues, en fonction des informations de la demande.
var supportedCultures = new[] { "en-US", "fr-FR" }; var localizationOptions = new RequestLocalizationOptions() .SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); app.UseRequestLocalization(localizationOptions);
GraphQL est un langage de requête pour les API. L'intégration d'une API Web .NET avec GraphQL permet une récupération de données plus efficace.
// Assume using a library like HotChocolate builder.Services .AddGraphQLServer() .AddQueryType<Query>(); app.MapGraphQL();
La surveillance et la télémétrie impliquent la collecte, l'analyse et l'action sur les données concernant les performances et l'utilisation de votre application.
// Assume using Application Insights builder.Services.AddApplicationInsightsTelemetry("YOUR_INSTRUMENTATION_KEY");
SignalR est une bibliothèque qui simplifie l'ajout de fonctionnalités Web en temps réel aux applications. La fonctionnalité Web en temps réel est la possibilité de permettre au code du serveur de transmettre instantanément le contenu aux clients connectés, sans obliger le serveur à attendre qu'un client demande de nouvelles données. SignalR est parfait pour développer des applications de chat, des tableaux de bord en temps réel et des applications Web plus interactives.
public class ChatHub : Hub { public async Task SendMessage(string user, string message) { // Call the broadcastMessage method to update clients. await Clients.All.SendAsync("broadcastMessage", user, message); } } // Startup or Program.cs app.MapHub<ChatHub>("/chathub");
Intégration dans Program.cs :
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // Other configurations... app.UseEndpoints(endpoints => { endpoints.MapHub<ChatHub>("/chathub"); }); }
Entity Framework Core permet le mappage de relations complexes entre entités, telles que un-à-un, un-à-plusieurs et plusieurs-à-plusieurs.
public class Author { public int AuthorId { get; set; } public string Name { get; set; } public ICollection<Book> Books { get; set; } } public class Book { public int BookId { get; set; } public string Title { get; set; } public int AuthorId { get; set; } public Author Author { get; set; } }
Les attributs de validation personnalisés vous permettent de définir votre logique de validation pour les modèles de données, en étendant les attributs de validation intégrés.
public class MyCustomValidationAttribute : ValidationAttribute { protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // Your custom validation logic here if (value is int intValue && intValue > 0) { return ValidationResult.Success; } return new ValidationResult("Value must be positive"); } } public class MyModel { [MyCustomValidationAttribute] public int MyProperty { get; set; } }
Le modèle d'options de .NET prend en charge des scénarios de configuration complexes, notamment des objets imbriqués, des listes et une validation.
public class MyOptions { public MyNestedOptions Nested { get; set; } public List<string> Items { get; set; } } public class MyNestedOptions { public string Key { get; set; } } // In Program.cs or Startup.cs builder.Services.Configure<MyOptions>(builder.Configuration.GetSection("MyOptions"));
La surveillance et le profilage d'une application peuvent identifier les goulots d'étranglement et les inefficacités, essentiels pour optimiser les performances.
app.UseMiniProfiler();
Améliorez la documentation de votre API en intégrant des commentaires XML dans votre interface utilisateur Swagger, offrant ainsi une expérience plus riche aux développeurs utilisant votre API.
builder.Services.AddSwaggerGen(c => { var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); });
La mondialisation et la localisation permettent à votre application de prendre en charge plusieurs langues et cultures, la rendant ainsi accessible à un public mondial.
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
Améliorer la sécurité de votre application Web en ajoutant divers en-têtes HTTP peut vous protéger contre les attaques et vulnérabilités courantes.
app.UseHsts(); app.UseXContentTypeOptions(); app.UseReferrerPolicy(opts => opts.NoReferrer()); app.UseXXssProtection(options => options.EnabledWithBlockMode()); app.UseXfo(options => options.Deny());
Les indicateurs de fonctionnalités vous permettent d'activer et de désactiver les fonctionnalités de votre application sans déployer de nouveau code, ce qui facilite les tests et les déploiements.
// Using a library like Microsoft.FeatureManagement builder.Services.AddFeatureManagement();
Blazor vous permet de créer des interfaces utilisateur Web interactives en utilisant C# au lieu de JavaScript. L'intégration de Blazor avec l'API Web offre une expérience de développement full-stack transparente.
// In a Blazor Server app @code { private IEnumerable<WeatherForecast> forecasts; protected override async Task OnInitializedAsync() { forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); } }
La compression des réponses peut réduire la taille de vos réponses API, améliorant ainsi les temps de chargement des clients sur des réseaux lents.
builder.Services.AddResponseCompression(options => { options.Providers.Add<GzipCompressionProvider>(); options.EnableForHttps = true; }); app.UseResponseCompression();
Merci de faire partie de la communauté C# ! Avant que tu partes:
Suivez-nous : X | LinkedIn | Dev.to | Noeud haché | Bulletin | Tumblr
Visitez nos autres plateformes : GitHub | Instagram | Tiktok | Quora | Quotidien.dev
Également publié ici