Sdílet prostřednictvím


Kurz: Provádění požadavků HTTP v konzolové aplikaci .NET pomocí jazyka C#

Tento kurz vytvoří aplikaci, která vydává požadavky HTTP na službu REST na GitHubu. Aplikace čte informace ve formátu JSON a převádí json na objekty jazyka C#. Převod z JSON na objekty jazyka C# se označuje jako deserializace.

V tomto kurzu se dozvíte, jak:

  • Odesílání požadavků HTTP
  • Deserializace odpovědí JSON
  • Nakonfigurujte deserializaci pomocí atributů.

Pokud chcete postupovat podle konečné ukázky pro tento kurz, můžete si ji stáhnout. Pokyny ke stažení najdete ve vzorech a návodech .

Požadavky

Vytvoření klientské aplikace

  1. Otevřete příkazový řádek a vytvořte nový adresář pro vaši aplikaci. Nastavte aktuální adresář.

  2. V okně konzoly zadejte následující příkaz:

    dotnet new console --name WebAPIClient
    

    Tento příkaz vytvoří počáteční soubory pro základní aplikaci Hello World. Název projektu je WebAPIClient.

  3. Přejděte do adresáře WebAPIClient a spusťte aplikaci.

    cd WebAPIClient
    
    dotnet run
    

    dotnet run automaticky spustí dotnet restore, aby se obnovily všechny závislosti, které aplikace potřebuje. V případě potřeby také spustí dotnet build. Měl by se zobrazit výstup aplikace "Hello, World!". V terminálu aplikaci zastavíte stisknutím klávesy Ctrl+C.

Vytváření požadavků HTTP

Tato aplikace volá rozhraní API GitHubu, aby získala informace o projektech v rámci .NET Foundation deštníku. Koncový bod je https://api.github.com/orgs/dotnet/repos. K načtení informací se vytvoří požadavek HTTP GET. Prohlížeče také odesílají požadavky HTTP GET, takže tuto adresu URL můžete vložit do adresního řádku prohlížeče a zjistit, jaké informace budete přijímat a zpracovávat.

Pomocí třídy HttpClient proveďte požadavky HTTP. HttpClient podporuje pouze asynchronní metody pro dlouhotrvající API. Následující kroky tedy vytvoří asynchronní metodu a zavolá ji z metody Main.

  1. Otevřete soubor Program.cs v adresáři projektu a nahraďte jeho obsah následujícím kódem:

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

    Tento kód:

    • Nahradí příkaz Console.WriteLine voláním ProcessRepositoriesAsync, který používá klíčové slovo await.
    • Definuje prázdnou metodu ProcessRepositoriesAsync.
  2. V Program třídě použijte HttpClient ke zpracování požadavků a odpovědí nahrazením obsahu následujícím jazykem C#.

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

    Tento kód:

    • Nastaví hlavičky HTTP pro všechny požadavky:
      • Hlavička Accept pro příjem odpovědí JSON
      • Záhlaví User-Agent. Tyto hlavičky jsou kontrolovány kódem serveru GitHubu a jsou nezbytné k načtení informací z GitHubu.
  3. V metodě ProcessRepositoriesAsync zavolejte koncový bod GitHubu, který vrátí seznam všech úložišť v rámci základní organizace .NET:

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

    Tento kód:

    • Očekává úlohu vrácenou voláním metody HttpClient.GetStringAsync(String). Tato metoda odešle požadavek HTTP GET na zadaný identifikátor URI. Tělo odpovědi je vráceno jako String, což je k dispozici po dokončení úkolu.
    • Řetězec odpovědi json se vytiskne do konzoly.
  4. Sestavte aplikaci a spusťte ji.

    dotnet run
    

    Není žádné varování při kompilaci, protože ProcessRepositoriesAsync nyní obsahuje operátor await. Výstup je dlouhý displej textu JSON.

Deserializace výsledku JSON

Následující kroky zjednodušují přístup k načtení a zpracování dat. K načtení a deserializaci výsledků JSON do objektů použijete metodu GetFromJsonAsync rozšíření, která je součástí 📦 balíčku NuGet System.Net.Http.Json .

  1. Vytvořte soubor s názvem Repository.cs a přidejte následující kód:

    public record class Repository(string Name);
    

    Předchozí kód definuje třídu, která představuje objekt JSON vrácený z rozhraní API GitHubu. Tuto třídu použijete k zobrazení seznamu názvů úložišť.

    JSON pro objekt úložiště obsahuje desítky vlastností, ale deserializována bude pouze Name vlastnost. Serializátor automaticky ignoruje vlastnosti JSON, které nejsou přítomny v cílové třídě. Tato funkce usnadňuje vytváření typů, které pracují pouze s podmnožinou polí ve velkém paketu JSON.

    I když metoda GetFromJsonAsync , kterou použijete v dalším bodě, má výhodu, že při názvech vlastností nerozlišuje malá a velká písmena, konvence jazyka C#je velká písmena názvů vlastností.

  2. HttpClientJsonExtensions.GetFromJsonAsync Pomocí metody můžete načíst a převést JSON na objekty jazyka C#. Volání GetStringAsync(String) v metodě ProcessRepositoriesAsync nahraďte následujícími řádky:

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

    Aktualizovaný kód nahrazuje GetStringAsync(String)HttpClientJsonExtensions.GetFromJsonAsync.

    Prvním argumentem GetFromJsonAsync metody await je výraz. await výrazy se mohou objevit téměř kdekoli ve vašem kódu, i když až dosud jste je viděli jen jako součást příkazu přiřazení. Další parametr requestUri je volitelný a nemusí být zadán, pokud byl již zadán při vytváření objektu client . Neposkytli client jste objekt s identifikátorem URI pro odeslání požadavku, takže jste teď zadali identifikátor URI. Poslední volitelný parametr, který CancellationToken je vynechán v fragmentu kódu.

    Metoda GetFromJsonAsync je obecná, což znamená, že zadáte argumenty pro typ objektů, které by se měly vytvořit z načteného textu JSON. V tomto příkladu deserializujete na List<Repository>, což je další obecný objekt, System.Collections.Generic.List<T>. Třída List<T> ukládá kolekci objektů. Argument typu deklaruje typ objektů uložených v List<T>. Argument typu je váš Repository záznam, protože text JSON představuje kolekci objektů úložiště.

  3. Přidejte kód pro zobrazení názvu každého úložiště. Nahraďte řádky, které čtou:

    Console.Write(json);
    

    s následujícím kódem:

    foreach (var repo in repositories ?? Enumerable.Empty<Repository>())
        Console.WriteLine(repo.Name);
    
  4. V horní části souboru by měly být uvedené následující direktivy using:

    using System.Net.Http.Headers;
    using System.Net.Http.Json;
    
  5. Spustit aplikaci.

    dotnet run
    

    Výstup je seznam názvů úložišť, která jsou součástí .NET Foundation.

Přepsat kód

Metoda ProcessRepositoriesAsync může provádět asynchronní práci a vrátit kolekci úložišť. Změňte metodu tak, aby vrátila Task<List<Repository>>, a přesuňte kód, který zapisuje do konzoly poblíž volajícího.

  1. Změňte podpis ProcessRepositoriesAsync tak, aby vrátil úkol, jehož výsledkem je seznam Repository objektů:

    static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
    
  2. Po zpracování odpovědi JSON vraťte úložiště:

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

    Kompilátor vygeneruje objekt Task<T> pro vrácenou hodnotu, protože jste tuto metodu označili jako async.

  3. Upravte soubor Program.cs a nahraďte volání ProcessRepositoriesAsync následujícím kódem, aby se zachytály výsledky a zapisují názvy jednotlivých úložišť do konzoly.

    var repositories = await ProcessRepositoriesAsync(client);
    
    foreach (var repo in repositories)
        Console.WriteLine(repo.Name);
    
  4. Spustit aplikaci.

    Výstup je stejný.

Deserializujte více vlastností

V následujících krocích rozšíříme kód pro zpracování více vlastností z vráceného JSON payloadu GitHub API. Pravděpodobně nebudete muset zpracovat každou vlastnost, ale přidáte několik dalších funkcí jazyka C#.

  1. Repository Obsah třídy nahraďte následující record definicí. Ujistěte se, že naimportujete System.Text.Json.Serialization namespace a výslovně použijete [JsonPropertyName] atribut pro mapování polí JSON na vlastnosti jazyka 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
      );
    

    Typy Uri a int mají vestavěné funkce pro převod z řetězcové reprezentace a na ni. K deserializaci z formátu řetězce JSON na tyto cílové typy není potřeba žádný další kód. Pokud paket JSON obsahuje data, která se nepřevedou na cílový typ, vyvolá akce serializace výjimku.

    JSON často používá lowercase nebo snake_case pro názvy vlastností. Pole podobná html_url a pushed_at nedodržují konvence pojmenování jazyka C# PascalCase. Použití [JsonPropertyName] zajišťuje, že tyto klíče JSON jsou správně svázané s odpovídajícími vlastnostmi jazyka C#, i když se jejich názvy liší v případě, že obsahují podtržítka. Tento přístup zaručuje předvídatelnou a stabilní deserializaci při povolování názvů vlastností PascalCase v jazyce C#. Kromě toho GetFromJsonAsync metoda je case-insensitive při porovnávání názvů vlastností, takže není nutná žádná další konverze.

  2. Aktualizujte smyčku foreach v souboru Program.cs, aby se zobrazily hodnoty vlastností:

    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. Spustit aplikaci.

    Seznam teď obsahuje další vlastnosti.

Přidejte vlastnost datum

Datum poslední push operace je naformátováno tímto způsobem v rámci JSON odpovědi:

2016-02-08T21:27:00Z

Tento formát je určen pro standard UTC (Coordinated Universal Time), takže výsledkem deserializace je hodnota DateTime, jejíž Kind vlastnost je Utc.

Pokud chcete získat datum a čas reprezentovaný ve vašem časovém pásmu, musíte napsat vlastní metodu převodu.

  1. V Repository.cspřidejte vlastnost pro vyjádření data a času UTC a jen pro čtení LastPush vlastnost, která vrací datum převedené na místní čas, měl by soubor vypadat takto:

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

    Vlastnost LastPush je definována pomocí výrazu jako členu pro přistupovač get. Není k dispozici žádný set příslušenství. Vynechání přístupového objektu set je jedním ze způsobů, jak definovat vlastnost jen pro čtení v jazyce C#. (Ano, v jazyce C# můžete vytvořit vlastnosti pouze pro zápis, ale jejich hodnota je omezená.)

  2. Do Program.cspřidejte další výstupní příkaz: znovu:

    Console.WriteLine($"Last push: {repo.LastPush}");
    
  3. Úplná aplikace by měla vypadat podobně jako v následujícím souboru Program.cs:

    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. Spustit aplikaci.

    Výstup zahrnuje datum a čas posledního odeslání do každého úložiště.

Další kroky

V tomto kurzu jste vytvořili aplikaci, která provádí webové požadavky a parsuje výsledky. Vaše verze aplikace by teď měla odpovídat dokončené ukázce .

Zjistěte více o tom, jak konfigurovat serializaci JSON v jak serializovat a deserializovat JSON v .NET.