Megosztás a következőn keresztül:


Oktatóanyag: HTTP-kérések létrehozása .NET-konzolalkalmazásban C használatával#

Ez az oktatóanyag létrehoz egy alkalmazást, amely HTTP-kéréseket ad ki egy REST-szolgáltatásnak a GitHubon. Az alkalmazás JSON formátumban olvassa be az információkat, és C#-objektumokká alakítja a JSON-t. A JSON-ból C#-objektumokká való konvertálást deszerializálásnak nevezzük.

Az oktatóanyag bemutatja, hogyan:

  • HTTP-kérések küldése.
  • JSON-válaszok deszerializálása.
  • Deszerializálás konfigurálása attribútumokkal.

Ha az oktatóanyag utolsó mintáját szeretné követni, letöltheti. A letöltési utasításokért tekintse meg példákat és oktatóanyagokat.

Előfeltételek

Az ügyfélalkalmazás létrehozása

  1. Nyisson meg egy parancssort, és hozzon létre egy új könyvtárat az alkalmazáshoz. Állítsa be az aktuális könyvtárat.

  2. Adja meg a következő parancsot egy konzolablakban:

    dotnet new console --name WebAPIClient
    

    Ez a parancs létrehozza a kezdőfájlokat egy alapszintű "Hello World" alkalmazáshoz. A projekt neve "WebAPIClient".

  3. Lépjen a "WebAPIClient" könyvtárba, és futtassa az alkalmazást.

    cd WebAPIClient
    
    dotnet run
    

    dotnet run automatikusan futtatja dotnet restore az alkalmazás által igényelt függőségek helyreállításához. dotnet build is fut, ha szükséges. Látnia kell az alkalmazás kimenetét "Hello, World!". A terminálban nyomja le a CtrlC+ az alkalmazás leállításához.

HTTP-kérések létrehozása

Ez az alkalmazás meghívja a GitHub API-t , hogy információkat kapjon a .NET Foundation esernyője alatti projektekről. A végpont az https://api.github.com/orgs/dotnet/repos. Az információk lekéréséhez HTTP GET kérést küld. A böngészők HTTP GET kéréseket is intéznek, így beillesztheti ezt az URL-címet a böngésző címsorába, hogy lássa, milyen adatokat fog kapni és feldolgozni.

HttpClient Az osztály használatával HTTP-kéréseket kezdeményezhet. HttpClient csak aszinkron metódusokat támogat a hosszú ideig futó API-khoz. Az alábbi lépések tehát létrehoznak egy aszinkron metódust, és meghívják a Main metódusból.

  1. Nyissa meg a fájlt a Program.cs projektkönyvtárban, és cserélje le a tartalmát a következőre:

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

    Ez a kód:

    • Az utasítást egy olyan hívásra Console.WriteLine cseréliProcessRepositoriesAsync, amely a kulcsszót await használja.
    • Üres ProcessRepositoriesAsync metódust definiál.
  2. Az Program osztályban használjon HttpClient egy metódust a kérések és válaszok kezelésére, a következő C#-kódra cserélve a tartalmat.

    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)
    {
    }
    

    Ez a kód:

    • HTTP-fejlécek beállítása az összes kéréshez:
      • Fejléc Accept jSON-válaszok elfogadásához
      • Egy User-Agent fejléc. Ezeket a fejléceket a GitHub-kiszolgálókód ellenőrzi, és az adatok GitHubról való lekéréséhez szükségesek.
  3. ProcessRepositoriesAsync A metódusban hívja meg a GitHub-végpontot, amely a .NET-alapszervezet összes adattárának listáját adja vissza:

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

    Ez a kód:

    • Várja a hívási HttpClient.GetStringAsync(String) metódusból visszaadott feladatot. Ez a metódus HTTP GET kérést küld a megadott URI-nak. A válasz tartalmát String formájában adjuk vissza, amely a feladat befejezésekor érhető el.
    • A válaszsztring json ki lesz írva a konzolra.
  4. Hozza létre és futtassa az alkalmazást.

    dotnet run
    

    Nincs összeállítási figyelmeztetés, mert a ProcessRepositoriesAsync most tartalmaz egy await operátort. A kimenet a JSON-szöveg hosszú megjelenítése.

A JSON-eredmény deszerializálása

Az alábbi lépések leegyszerűsítik az adatok beolvasásának és feldolgozásának megközelítését. A GetFromJsonAsync bővítménymetódus használatával 📦 beolvassa és deszerializálja a JSON-eredményeket objektumokká.

  1. Hozzon létre egy Repository.cs nevű fájlt, és adja hozzá a következő kódot:

    public record class Repository(string Name);
    

    Az előző kód egy osztályt határoz meg, amely a GitHub API-ból visszaadott JSON-objektumot jelöli. Ezzel az osztálysal megjelenítheti az adattárnevek listáját.

    Az adattárobjektum JSON-ja több tucat tulajdonságot tartalmaz, de csak a Name tulajdonság lesz deszerializálva. A szerializáló automatikusan figyelmen kívül hagyja azokat a JSON-tulajdonságokat, amelyek esetében nincs egyezés a célosztályban. Ez a funkció megkönnyíti az olyan típusok létrehozását, amelyek csak a mezők egy részhalmazával működnek egy nagy JSON-csomagban.

    Bár a GetFromJsonAsync következő pontban használt módszer előnye, hogy a kis- és nagybetűk nem érzékenek a tulajdonságnevekhez, a C#-konvenció a tulajdonságnevek első betűjének nagybetűssé ciója.

  2. A metódus használatával HttpClientJsonExtensions.GetFromJsonAsync beolvassa és C#-objektumokká konvertálja a JSON-t. Cserélje le a GetStringAsync(String) metódusban a ProcessRepositoriesAsync hívást az alábbi sorokra:

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

    A frissített kód a GetStringAsync(String)-t lecseréli HttpClientJsonExtensions.GetFromJsonAsync-re.

    A metódus első argumentuma GetFromJsonAsync egy await kifejezés. await a kifejezések szinte bárhol megjelenhetnek a kódban, bár eddig csak egy hozzárendelési utasítás részeként látta őket. A következő paraméter nem kötelező, requestUri és nem kell megadni, ha már meg lett adva az client objektum létrehozásakor. Nem adta meg az client objektumnak a kérés küldéséhez szükséges URI-t, ezért most adta meg az URI-t. Az utolsó választható paraméter, a CancellationToken kódrészlet kihagyva.

    A GetFromJsonAsync metódus általános, ami azt jelenti, hogy típusargumentumokat ad meg ahhoz, hogy milyen típusú objektumokat kell létrehozni a beolvasott JSON-szövegből. Ebben a példában egy List<Repository> típusú objektumot deszerializálsz, ami egy másik általános objektum, egy System.Collections.Generic.List<T>. Az List<T> osztály objektumgyűjteményt tárol. A típusargumentum deklarálja a fájlban List<T>tárolt objektumok típusát. A típusargumentum a Repository rekord, mert a JSON-szöveg adattárobjektumok gyűjteményét jelöli.

  3. Adjon hozzá kódot az egyes adattárak nevének megjelenítéséhez. Cserélje le azokat a sorokat, amelyek így szólnak:

    Console.Write(json);
    

    a következő kóddal:

    foreach (var repo in repositories ?? Enumerable.Empty<Repository>())
        Console.WriteLine(repo.Name);
    
  4. A fájl tetején a következő using irányelveknek kell szerepelnie:

    using System.Net.Http.Headers;
    using System.Net.Http.Json;
    
  5. Indítsa el az alkalmazást.

    dotnet run
    

    A kimenet a .NET Foundation részét képező adattárak nevének listája.

A kód újrabontása

A ProcessRepositoriesAsync metódus képes elvégezni az aszinkron munkát, és visszaadni az adattárak gyűjteményét. Módosítsa ezt a metódust úgy, hogy Task<List<Repository>> értéket adjon vissza, és helyezze át a konzolra író kódot a hívó közelébe.

  1. Módosítsa a ProcessRepositoriesAsync aláírását úgy, hogy egy feladatot adjon vissza, amelynek eredménye egy Repository objektumokból álló lista.

    static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
    
  2. A JSON-válasz feldolgozása után adja vissza az adattárakat:

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

    A fordító létrehozza az Task<T> objektumot a visszatérési értékhez, mert ezt a metódust async-ként jelölte meg.

  3. Módosítsa a Program.cs fájlt, és cserélje le a hívást ProcessRepositoriesAsync a következőre az eredmények rögzítéséhez és az egyes adattárak nevének a konzolra való írásához.

    var repositories = await ProcessRepositoriesAsync(client);
    
    foreach (var repo in repositories)
        Console.WriteLine(repo.Name);
    
  4. Indítsa el az alkalmazást.

    A kimenet ugyanaz.

További tulajdonságok deszerializálása

Az alábbi lépésekben kiterjesztjük a kódot, hogy a GitHub API által visszaadott JSON hasznos adatokból további tulajdonságokat dolgozzanak fel. Valószínűleg nem kell minden tulajdonságot feldolgoznia, de néhány további C#-funkciót is bemutat.

  1. Cserélje le az Repository osztály tartalmát a következő record definícióra. Ügyeljen arra, hogy importálja a System.Text.Json.Serialization névteret, és alkalmazza az attribútumot a [JsonPropertyName] JSON-mezők C#-tulajdonságokra való leképezéséhez.

     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
      );
    

    A Uri típusok beépített funkcióval rendelkeznek a string reprezentációvá való átalakításhoz és visszaalakításhoz. Nincs szükség további kódra a JSON-sztringformátumból a céltípusokra való deszerializáláshoz. Ha a JSON-csomag olyan adatokat tartalmaz, amelyek nem konvertálhatók céltípusra, a szerializálási művelet kivételt eredményez.

    A JSON gyakran használ lowercase vagy snake_case tulajdonságneveket. Olyan mezők, mint html_url és pushed_at, nem követik a PascalCase elnevezési konvencióit a C#-ban. [JsonPropertyName] használata biztosítja, hogy ezek a JSON-kulcsok helyesen legyenek kötve a megfelelő C#-tulajdonságaikhoz, még akkor is, ha a nevük különböző esetű vagy aláhúzásokat tartalmaz. Ez a megközelítés kiszámítható és stabil deszerializálást biztosít, miközben engedélyezi a PascalCase tulajdonságneveket a C#-ban. Emellett a GetFromJsonAsync metódus case-insensitive a tulajdonságnevek összehasonlításánál, így nincs szükség további átalakításra.

  2. Frissítse a foreach ciklust a Program.cs fájlban a tulajdonságértékek megjelenítéséhez:

    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. Indítsa el az alkalmazást.

    A lista most már tartalmazza a további tulajdonságokat.

Dátumtulajdonság hozzáadása

Az utolsó leküldéses művelet dátuma így van formázva a JSON-válaszban:

2016-02-08T21:27:00Z

Ez a formátum az egyezményes világidő (UTC) formátuma, így a deszerializálás eredménye olyan DateTime érték, amelynek Kind tulajdonsága a Utc.

Ha az időzónában meg szeretné jeleníteni a dátumot és az időt, egyéni konverziós módszert kell írnia.

  1. A Repository.cs adjon hozzá egy tulajdonságot a dátum és az idő UTC-ábrázolásához, valamint egy olvasható LastPush tulajdonságot, amely a helyi idővé konvertált dátumot adja vissza, a fájlnak a következőhöz hasonlóan kell kinéznie:

    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();
    }
    

    A LastPush tulajdonságot a tartozék számára kifejezés-alapú tag használatával definiálják. Nincs set tartozék. A set hozzáférő kihagyása egy írásvédett tulajdonságot definiál a C#-ban. (Igen, írásvédett tulajdonságokat is létrehozhat a C#-ban, de értékük korlátozott.)

  2. Adjon hozzá egy másik kimeneti utasítást a Program.cs: ismét:

    Console.WriteLine($"Last push: {repo.LastPush}");
    
  3. A teljes alkalmazásnak a következő Program.cs fájlhoz kell hasonlítania:

    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. Indítsa el az alkalmazást.

    A kimenet tartalmazza az egyes adattárakba való utolsó leküldés dátumát és időpontját.

Következő lépések

Ebben az oktatóanyagban létrehozott egy alkalmazást, amely webes kéréseket készít, és elemzi az eredményeket. Az alkalmazás verziójának most már meg kell egyeznie a kész mintával.

További információ a JSON szerializálás konfigurálásáról a JSON szerializálásának és deszerializálásának (marshal és unmarshal) a .NET-ben való konfigurálásáról.