Partager via


Tutoriel : Effectuer des requêtes HTTP dans une application console .NET à l’aide de C#

Ce tutoriel génère une application qui émet des requêtes HTTP vers un service REST sur GitHub. L’application lit les informations au format JSON et convertit le JSON en objets C#. La conversion de JSON en objets C# est appelée désérialisation.

Le tutoriel montre comment :

  • Envoyer des requêtes HTTP.
  • Désérialiser les réponses JSON.
  • Configurez la désérialisation avec des attributs.

Si vous préférez suivre l’exemple final de ce didacticiel, vous pouvez le télécharger. Pour obtenir des instructions de téléchargement, consultez Exemples et didacticiels.

Prerequisites

Créer l’application cliente

  1. Ouvrez une invite de commandes et créez un répertoire pour votre application. Faites en sorte que le répertoire actif.

  2. Entrez la commande suivante dans une fenêtre de console :

    dotnet new console --name WebAPIClient
    

    Cette commande crée les fichiers de démarrage pour une application « Hello World » de base. Le nom du projet est « WebAPIClient ».

  3. Accédez au répertoire « WebAPIClient » et exécutez l’application.

    cd WebAPIClient
    
    dotnet run
    

    dotnet run s’exécute dotnet restore automatiquement pour restaurer les dépendances dont l’application a besoin. Il s’exécute dotnet build également si nécessaire. Vous devez voir la sortie "Hello, World!"de l’application . Dans votre terminal, appuyez sur Ctrl+C pour arrêter l’application.

Effectuer des requêtes HTTP

Cette application appelle l’API GitHub pour obtenir des informations sur les projets sous le parapluie .NET Foundation . Le point de terminaison est https://api.github.com/orgs/dotnet/repos. Pour récupérer des informations, il effectue une requête HTTP GET. Les navigateurs effectuent également des requêtes HTTP GET. Vous pouvez donc coller cette URL dans la barre d’adresses de votre navigateur pour voir les informations que vous recevrez et traiterez.

Utilisez la HttpClient classe pour effectuer des requêtes HTTP. HttpClient prend uniquement en charge les méthodes asynchrones pour ses API de longue durée. Ainsi, les étapes suivantes créent une méthode asynchrone et l’appellent à partir de la méthode Main.

  1. Ouvrez le Program.cs fichier dans votre répertoire de projet et remplacez son contenu par les éléments suivants :

    await ProcessRepositoriesAsync();
    
    static async Task ProcessRepositoriesAsync(HttpClient client)
    {
    }
    

    Ce code :

    • Remplace l’instruction Console.WriteLine par un appel qui ProcessRepositoriesAsync utilise le await mot clé.
    • Définit une méthode vide ProcessRepositoriesAsync .
  2. Dans la Program classe, utilisez un HttpClient pour gérer les requêtes et les réponses, en remplaçant le contenu par le code C#suivant.

    using System.Net.Http.Headers;
    
    using HttpClient client = new();
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
    client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
    
    await ProcessRepositoriesAsync(client);
    
    static async Task ProcessRepositoriesAsync(HttpClient client)
    {
    }
    

    Ce code :

    • Configure les en-têtes HTTP pour toutes les requêtes :
      • En-tête Accept pour accepter les réponses JSON
      • En-tête User-Agent . Ces en-têtes sont vérifiés par le code du serveur GitHub et sont nécessaires pour récupérer des informations à partir de GitHub.
  3. Dans la ProcessRepositoriesAsync méthode, appelez le point de terminaison GitHub qui retourne une liste de tous les référentiels sous l’organisation .NET Foundation :

     static async Task ProcessRepositoriesAsync(HttpClient client)
     {
         var json = await client.GetStringAsync(
             "https://api.github.com/orgs/dotnet/repos");
    
         Console.Write(json);
     }
    

    Ce code :

    • Attend la tâche retournée par la méthode appelante HttpClient.GetStringAsync(String) . Cette méthode envoie une requête HTTP GET à l’URI spécifié. Le corps de la réponse est retourné en tant que String, qui est disponible lorsque la tâche se termine.
    • La chaîne json de réponse est imprimée dans la console.
  4. Générez l’application et exécutez-la.

    dotnet run
    

    Il n’y a pas d’avertissement de build, car l’opérateur ProcessRepositoriesAsync contient await maintenant. La sortie est un long affichage du texte JSON.

Désérialiser le résultat JSON

Les étapes suivantes simplifient l’approche permettant d’extraire les données et de les traiter. Vous allez utiliser la GetFromJsonAsync méthode d’extension qui fait partie du 📦 package NuGet System.Net.Http.Json pour extraire et désérialiser les résultats JSON dans des objets.

  1. Créez un fichier nommé Repository.cs et ajoutez le code suivant :

    public record class Repository(string Name);
    

    Le code précédent définit une classe pour représenter l’objet JSON retourné par l’API GitHub. Vous utiliserez cette classe pour afficher une liste de noms de référentiels.

    Le json d’un objet de référentiel contient des dizaines de propriétés, mais seule la Name propriété sera désérialisée. Le sérialiseur ignore automatiquement les propriétés JSON pour lesquelles il n’existe aucune correspondance dans la classe cible. Cette fonctionnalité facilite la création de types qui fonctionnent uniquement avec un sous-ensemble de champs dans un paquet JSON volumineux.

    Bien que la GetFromJsonAsync méthode que vous utiliserez dans le point suivant a l’avantage d’être insensible à la casse lorsqu’il s’agit de noms de propriétés, la convention C# consiste à mettre en majuscule la première lettre des noms de propriétés.

  2. Utilisez la HttpClientJsonExtensions.GetFromJsonAsync méthode pour extraire et convertir JSON en objets C#. Remplacez l’appel dans GetStringAsync(String) la ProcessRepositoriesAsync méthode par les lignes suivantes :

    var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos");
    

    Le code mis à jour remplace GetStringAsync(String)HttpClientJsonExtensions.GetFromJsonAsyncpar .

    Le premier argument à GetFromJsonAsync la méthode est une await expression. await les expressions peuvent apparaître presque n’importe où dans votre code, même si jusqu’à présent, vous les avez vues uniquement dans le cadre d’une instruction d’affectation. Le paramètre suivant est requestUri facultatif et ne doit pas être fourni s’il a déjà été spécifié lors de la création de l’objet client . Vous n’avez pas fourni l’objet à l’URI client pour envoyer la demande. Vous avez donc spécifié l’URI maintenant. Le dernier paramètre facultatif est CancellationToken omis dans l’extrait de code.

    La GetFromJsonAsync méthode est générique, ce qui signifie que vous fournissez des arguments de type pour le type d’objets à créer à partir du texte JSON extrait. Dans cet exemple, vous désérialisez un List<Repository>objet générique, un System.Collections.Generic.List<T>. La List<T> classe stocke une collection d’objets. L’argument de type déclare le type d’objets stockés dans le List<T>. L’argument de type est votre Repository enregistrement, car le texte JSON représente une collection d’objets de référentiel.

  3. Ajoutez du code pour afficher le nom de chaque référentiel. Remplacez les lignes qui lisent :

    Console.Write(json);
    

    avec le code suivant :

    foreach (var repo in repositories ?? Enumerable.Empty<Repository>())
        Console.WriteLine(repo.Name);
    
  4. Les directives suivantes using doivent être présentes en haut du fichier :

    using System.Net.Http.Headers;
    using System.Net.Http.Json;
    
  5. Exécutez l’application.

    dotnet run
    

    La sortie est une liste des noms des référentiels qui font partie de .NET Foundation.

Refactoriser le code

La ProcessRepositoriesAsync méthode peut effectuer le travail asynchrone et retourner une collection des référentiels. Modifiez cette méthode pour retourner Task<List<Repository>>et déplacez le code qui écrit dans la console près de son appelant.

  1. Modifiez la signature de retour d’une ProcessRepositoriesAsync tâche dont le résultat est une liste d’objets Repository :

    static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
    
  2. Retournez les référentiels après avoir traité la réponse JSON :

    var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos");
    return repositories ?? new();
    

    Le compilateur génère l’objet Task<T> pour la valeur de retour, car vous avez marqué cette méthode comme async.

  3. Modifiez le fichier Program.cs , en remplaçant l’appel par ce qui ProcessRepositoriesAsync suit pour capturer les résultats et écrire chaque nom de référentiel dans la console.

    var repositories = await ProcessRepositoriesAsync(client);
    
    foreach (var repo in repositories)
        Console.WriteLine(repo.Name);
    
  4. Exécutez l’application.

    La sortie est la même.

Désérialiser d’autres propriétés

Dans les étapes suivantes, nous étendons le code pour traiter davantage de propriétés à partir de la charge utile JSON retournée par l’API GitHub. Vous n’aurez probablement pas besoin de traiter chaque propriété, mais l’ajout de quelques-uns illustre des fonctionnalités C# supplémentaires.

  1. Remplacez le contenu de la Repository classe par la définition suivante record . Veillez à importer l’espace de noms et à appliquer l’attribut System.Text.Json.Serialization[JsonPropertyName] pour mapper explicitement les champs JSON aux propriétés C#.

     using System.Text.Json.Serialization;
    
     public record class Repository(
       string Name,
       string Description,
       [property: JsonPropertyName("html_url")] Uri GitHubHomeUrl,
       Uri Homepage,
       int Watchers,
       [property: JsonPropertyName("pushed_at")] DateTime LastPushUtc
      );
    

    Les Uri types et int les types ont des fonctionnalités intégrées à convertir en et à partir de la représentation sous forme de chaîne. Aucun code supplémentaire n’est nécessaire pour désérialiser du format de chaîne JSON à ces types cibles. Si le paquet JSON contient des données qui ne sont pas converties en type cible, l’action de sérialisation lève une exception.

    JSON utilise lowercase souvent ou snake_case pour les noms de propriétés. Les champs comme html_url et pushed_at ne suivent pas les conventions d’affectation de noms C# PascalCase. L’utilisation [JsonPropertyName] garantit que ces clés JSON sont correctement liées à leurs propriétés C# correspondantes, même si leurs noms diffèrent dans le cas ou contiennent des traits de soulignement. Cette approche garantit la désérialisation prévisible et stable tout en autorisant les noms de propriétés PascalCase en C#. En outre, la GetFromJsonAsync méthode est case-insensitive en correspondance avec les noms de propriétés, donc aucune autre conversion n’est nécessaire.

  2. Mettez à jour la foreach boucle dans le fichier Program.cs pour afficher les valeurs de propriété :

    foreach (var repo in repositories)
    {
        Console.WriteLine($"Name: {repo.Name}");
        Console.WriteLine($"Homepage: {repo.Homepage}");
        Console.WriteLine($"GitHub: {repo.GitHubHomeUrl}");
        Console.WriteLine($"Description: {repo.Description}");
        Console.WriteLine($"Watchers: {repo.Watchers:#,0}");
        Console.WriteLine();
    }
    
  3. Exécutez l’application.

    La liste inclut désormais les propriétés supplémentaires.

Ajouter une propriété date

La date de la dernière opération push est mise en forme de cette façon dans la réponse JSON :

2016-02-08T21:27:00Z

Ce format est destiné au temps universel coordonné (UTC), de sorte que le résultat de la désérialisation est une DateTime valeur dont Kind la propriété est Utc.

Pour obtenir une date et une heure représentées dans votre fuseau horaire, vous devez écrire une méthode de conversion personnalisée.

  1. Dans Repository.cs, ajoutez une propriété pour la représentation UTC de la date et de l’heure et une propriété en lecture seule LastPush qui retourne la date convertie en heure locale, le fichier doit ressembler à ce qui suit :

    using System.Text.Json.Serialization;
    
    public record class Repository(
        string Name,
        string Description,
        [property: JsonPropertyName("html_url")] Uri GitHubHomeUrl,
        Uri Homepage,
        int Watchers,
        [property: JsonPropertyName("pushed_at")] DateTime LastPushUtc
        )
    {
        public DateTime LastPush => LastPushUtc.ToLocalTime();
    }
    

    La LastPush propriété est définie à l’aide d’un membre expression-bodied pour l’accesseur get . Il n’y a pas set d’accesseur. L’omission de l’accesseur set est une façon de définir une propriété en lecture seule en C#. (Oui, vous pouvez créer des propriétés en écriture seule en C#, mais leur valeur est limitée.)

  2. Ajoutez une autre instruction de sortie dans Program.cs :

    Console.WriteLine($"Last push: {repo.LastPush}");
    
  3. L’application complète doit ressembler au fichier Program.cs suivant :

    using System.Net.Http.Headers;
    using System.Net.Http.Json;
    
    using HttpClient client = new();
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
    client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
    
    var repositories = await ProcessRepositoriesAsync(client);
    
    foreach (var repo in repositories)
    {
        Console.WriteLine($"Name: {repo.Name}");
        Console.WriteLine($"Homepage: {repo.Homepage}");
        Console.WriteLine($"GitHub: {repo.GitHubHomeUrl}");
        Console.WriteLine($"Description: {repo.Description}");
        Console.WriteLine($"Watchers: {repo.Watchers:#,0}");
        Console.WriteLine($"{repo.LastPush}");
        Console.WriteLine();
    }
    
    static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
    {
        var repositories = await client.GetFromJsonAsync<List<Repository>>("https://api.github.com/orgs/dotnet/repos");
        return repositories ?? new List<Repository>();
    }
    
  4. Exécutez l’application.

    La sortie inclut la date et l’heure du dernier push vers chaque référentiel.

Étapes suivantes

Dans ce tutoriel, vous avez créé une application qui effectue des requêtes web et analyse les résultats. Votre version de l’application doit maintenant correspondre à l’exemple terminé.

Apprenez-en davantage sur la configuration de la sérialisation JSON dans Comment sérialiser et désérialiser (marshaler et désérialiser) JSON dans .NET.