Kurz: Vytváření požadavků HTTP v konzolové aplikaci .NET pomocí jazyka C #

Tento kurz sestaví aplikaci, která vydává požadavky HTTP na službu REST na GitHubu. Aplikace čte informace ve formátu JSON a převede ho na objekty jazyka C#. Převod z objektů 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 poslední ukázky pro tento kurz, můžete si ji stáhnout. Pokyny ke stažení najdete v tématu Ukázky a kurzy.

Požadavky

  • .NET SDK 6.0 nebo novější
  • Editor kódu, například [Visual Studio Code (opensourcový multiplatformní editor). Ukázkovou aplikaci můžete spustit ve Windows, Linuxu nebo macOS nebo v kontejneru Dockeru.

Vytvoření klientské aplikace

  1. Otevřete příkazový řádek a vytvořte pro svou aplikaci nový adresář. Nastavte ho jako 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í Hello World aplikaci. Název projektu je WebAPIClient.

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

    cd WebAPIClient
    
    dotnet run
    

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

Vytváření požadavků HTTP

Tato aplikace volá rozhraní API GitHubu , aby získala informace o projektech v rámci zastřešující platformy .NET Foundation . Koncový bod je https://api.github.com/orgs/dotnet/repos. Za účelem načtení informací vytvoří požadavek HTTP GET. Prohlížeče také zasílaly 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.

HttpClient Pomocí třídy můžete vytvářet požadavky HTTP. HttpClient podporuje pouze asynchronní metody pro dlouhotrvající rozhraní API. Následující kroky tedy vytvoří asynchronní metodu a zavolá ji z metody Main.

  1. Program.cs Otevřete soubor 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:

    • Console.WriteLine Nahradí příkaz volánímProcessRepositoriesAsync, které používá await klíčové slovo.
    • Definuje prázdnou ProcessRepositoriesAsync metodu.
  2. Program Ve třídě použijte k zpracování požadavků a odpovědí an HttpClient tím, že nahradíte obsah 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 GitHub a jsou nezbytné k načtení informací z GitHubu.
  3. ProcessRepositoriesAsync V metodě 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:

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

    dotnet run
    

    Neexistuje žádné upozornění na sestavení, ProcessRepositoriesAsync protože teď obsahuje await operátor. Výstupem je dlouhé zobrazení textu JSON.

Deserializace výsledku JSON

Následující kroky převedou odpověď JSON na objekty jazyka C#. Třídu použijete System.Text.Json.JsonSerializer k deserializaci JSON na objekty.

  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 představující 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 pouze vlastnost name bude deserializována. Serializátor automaticky ignoruje vlastnosti JSON, pro které není v cílové třídě žádná shoda. Tato funkce usnadňuje vytváření typů, které pracují pouze s podmnožinou polí ve velkém paketu JSON.

    Konvence jazyka C# spočívá v tom, že se první písmeno názvů vlastností změní na velká písmena, ale name tato vlastnost začíná malým písmenem, protože přesně odpovídá tomu, co je ve formátu JSON. Později se dozvíte, jak používat názvy vlastností jazyka C#, které neodpovídají názvům vlastností JSON.

  2. Použijte serializátor k převodu JSON na objekty jazyka C#. Nahraďte volání GetStringAsync(String) v ProcessRepositoriesAsync metodě následujícími řádky:

    await using Stream stream =
        await client.GetStreamAsync("https://api.github.com/orgs/dotnet/repos");
    var repositories =
        await JsonSerializer.DeserializeAsync<List<Repository>>(stream);
    

    Aktualizovaný kód nahradí GetStringAsync(String) kódem GetStreamAsync(String). Tato metoda serializátoru používá jako zdroj datový proud místo řetězce.

    Prvním argumentem await je JsonSerializer.DeserializeAsync<TValue>(Stream, JsonSerializerOptions, CancellationToken) výraz. await Výrazy se můžou zobrazit téměř kdekoli v kódu, i když jste je dosud viděli jenom jako součást příkazu přiřazení. Další dva parametry JsonSerializerOptions a CancellationTokenjsou volitelné a ve fragmentu kódu se vynechají.

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

  3. Přidejte kód, který zobrazí názvy jednotlivých úložišť. Nahraďte řádky s textem:

    Console.Write(json);
    

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

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

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

    dotnet run
    

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

Konfigurace deserializace

  1. V souboru Repository.cs nahraďte obsah souboru následujícím jazykem C#.

    using System.Text.Json.Serialization;
    
    public record class Repository(
        [property: JsonPropertyName("name")] string Name);
    

    Tento kód:

    • Změní název vlastnosti na nameName.
    • Přidá parametr, který JsonPropertyNameAttribute určí, jak se tato vlastnost bude v kódu JSON vypadat.
  2. V souboru Program.cs aktualizujte kód tak, aby používal nové nastavení velkých písmen Name vlastnosti:

    foreach (var repo in repositories)
       Console.Write(repo.Name);
    
  3. Spustit aplikaci.

    Výstup je stejný.

Refaktoring kódu

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

  1. Změňte podpis objektu ProcessRepositoriesAsync tak, aby se 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ě:

    await using Stream stream =
        await client.GetStreamAsync("https://api.github.com/orgs/dotnet/repos");
    var repositories =
        await JsonSerializer.DeserializeAsync<List<Repository>>(stream);
    return repositories ?? new();
    

    Kompilátor vygeneruje Task<T> objekt pro návratnou 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, který zachytí výsledky a zapíše názvy jednotlivých úložišť do konzoly.

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

    Výstup je stejný.

Deserializace dalších vlastností

Následující postup přidá kód pro zpracování více vlastností v přijatém paketu JSON. Pravděpodobně nebudete chtít zpracovávat všechny vlastnosti, ale přidání několika dalších ukazuje další funkce jazyka C#.

  1. Nahraďte obsah Repository třídy následující record definicí:

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

    Typy Uri a int mají předdefinované funkce pro převod na řetězcovou reprezentaci a z reprezentace. 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, akce serializace vyvolá výjimku.

  2. Aktualizujte smyčku foreach v souboru Program.cs tak, aby zobrazovala 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řidání vlastnosti data

Datum poslední operace vložení je v odpovědi JSON naformátované tímto způsobem:

2016-02-08T21:27:00Z

Tento formát je 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 souboru Repository.cs přidejte vlastnost pro vyjádření data a času VE FORMÁTU UTC a vlastnost jen LastPush pro čtení, která vrací datum převedené na místní čas. Soubor by měl vypadat takto:

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

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

  2. Přidejte další výstupní příkaz v souboru Program.cs: znovu:

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

    using System.Net.Http.Headers;
    using System.Text.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)
    {
        await using Stream stream =
            await client.GetStreamAsync("https://api.github.com/orgs/dotnet/repos");
        var repositories =
            await JsonSerializer.DeserializeAsync<List<Repository>>(stream);
        return repositories ?? new();
    }
    
  4. Spustit aplikaci.

    Výstup obsahuje datum a čas posledního nasdílení změ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.

Další informace o konfiguraci serializace JSON najdete v tématu Jak serializovat a deserializovat (zařazovat a zrušitmarshal) JSON v .NET.