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
Otevřete příkazový řádek a vytvořte pro svou aplikaci nový adresář. Nastavte ho jako aktuální adresář.
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.
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.
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.
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.
- Hlavička
- Nastaví hlavičky HTTP pro všechny požadavky:
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.
Sestavte aplikaci a spusťte ji.
dotnet run
Neexistuje žádné upozornění na sestavení,
ProcessRepositoriesAsync
protože teď obsahujeawait
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.
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.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 parametryJsonSerializerOptions
aCancellationToken
jsou 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 naList<Repository>
objekt , což je další obecný objekt , System.Collections.Generic.List<T>objekt . TřídaList<T>
ukládá kolekci objektů. Argument type deklaruje typ objektů uložených v objektuList<T>
. Argument type je vášRepository
záznam, protože text JSON představuje kolekci objektů úložiště.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);
V horní části souboru by měly být uvedené následující
using
direktivy:using System.Net.Http.Headers; using System.Text.Json;
Spustit aplikaci.
dotnet run
Výstupem je seznam názvů úložišť, které jsou součástí .NET Foundation.
Konfigurace deserializace
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
name
Name
. - Přidá parametr, který JsonPropertyNameAttribute určí, jak se tato vlastnost bude v kódu JSON vypadat.
- Změní název vlastnosti na
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);
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.
Změňte podpis objektu
ProcessRepositoriesAsync
tak, aby se vrátil úkol, jehož výsledkem je seznamRepository
objektů:static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
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 jakoasync
.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);
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#.
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.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(); }
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.
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 objektuset
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á.)Přidejte další výstupní příkaz v souboru Program.cs: znovu:
Console.WriteLine($"Last push: {repo.LastPush}");
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(); }
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.