Client HTTP en C# : faire des requêtes correctement et efficacement

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi un client HTTP correct en C# ?

Dans le développement moderne, pratiquement aucune application ne peut se passer d'interagir avec des services externes. Qu'il s'agisse d'envoyer des données à un serveur, d'obtenir le taux de change ou de travailler avec une API cloud, tout cela nécessite une implémentation correcte des requêtes HTTP. Dans l'écosystème C# (.NET), l'outil principal pour cette tâche est la classe HttpClient. Cependant, de nombreux développeurs, en particulier les débutants, commettent des erreurs typiques : créer une nouvelle instance de HttpClient pour chaque requête, oublier de gérer les exceptions ou mal travailler avec l'asynchronisme.

Dans cet article, nous allons voir comment organiser correctement un client HTTP en C#, examiner l'envoi de requêtes GET et POST, la gestion des en-têtes et du corps de la requête, ainsi que les bonnes pratiques de gestion des erreurs. Après avoir lu cet article, vous serez en mesure d'écrire un code fiable et performant pour interagir avec n'importe quelle API REST.

Fondamentaux du travail avec HttpClient en C#

La classe HttpClient fait partie de l'espace de noms System.Net.Http et est disponible dans toutes les versions modernes de .NET (Core, 5, 6, 7, 8 et supérieures). Son principal avantage est la prise en charge des opérations asynchrones et la gestion automatique du pool de connexions.

Création correcte de HttpClient

Règle la plus importante : ne créez pas un nouveau HttpClient pour chaque requête. Cela peut entraîner un épuisement des sockets (socket exhaustion). Utilisez plutôt une seule instance pour toute la durée de vie de l'application ou utilisez IHttpClientFactory.

// ❌ Mauvais : nouveau HttpClient pour chaque requête
using (var client = new HttpClient())
{
    var response = await client.GetAsync("https://api.example.com");
}

// ✅ Bon : un seul HttpClient pour toutes les requêtes
public class MyHttpService
{
    private static readonly HttpClient _client = new HttpClient();
    
    public async Task<string> GetDataAsync(string url)
    {
        return await _client.GetStringAsync(url);
    }
}

Paramètres de base

Lors de l'initialisation de HttpClient, vous pouvez définir l'adresse de base, les délais d'attente et les en-têtes par défaut :

public class ApiClient
{
    private readonly HttpClient _httpClient;
    
    public ApiClient()
    {
        _httpClient = new HttpClient
        {
            BaseAddress = new Uri("https://api.pythonlib.ru/"),
            Timeout = TimeSpan.FromSeconds(10)
        };
        
        // En-têtes qui seront envoyés avec chaque requête
        _httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
    }
}

Envoi de requêtes GET et POST

Examinons les deux types de requêtes HTTP les plus courants : la récupération de données (GET) et l'envoi de données (POST).

Requête GET : récupération de données

Une requête GET est utilisée pour lire des données depuis le serveur. Elle ne doit pas modifier l'état de la ressource et ne contient pas de corps.

public async Task<string> GetUserAsync(int userId)
{
    try
    {
        var response = await _httpClient.GetAsync($"/api/users/{userId}");
        response.EnsureSuccessStatusCode(); // Lèvera une exception en cas d'erreur
        return await response.Content.ReadAsStringAsync();
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"Erreur de requête : {ex.Message}");
        throw;
    }
}

Pour les cas simples, vous pouvez utiliser la forme abrégée :

string json = await _httpClient.GetStringAsync("/api/users/42");

Requête POST : envoi de données

Une requête POST est utilisée pour créer de nouvelles ressources. Les données sont transmises dans le corps de la requête, le plus souvent au format JSON.

public async Task<User> CreateUserAsync(User newUser)
{
    // Sérialiser l'objet en JSON
    var json = JsonSerializer.Serialize(newUser);                

Blogs

Book Recommendations