Öğretici: C kullanarak bir .NET konsol uygulamasında HTTP istekleri yapma #
Bu öğreticide GitHub'da bir REST hizmetine HTTP istekleri veren bir uygulama derlenir. Uygulama bilgileri JSON biçiminde okur ve JSON'ı C# nesnelerine dönüştürür. JSON'dan C# nesnelerine dönüştürme , seri durumdan çıkarma olarak bilinir.
Öğreticide şunların nasıl yapılacağını gösterilmektedir:
- HTTP istekleri gönderin.
- JSON yanıtlarını seri durumdan çıkarma.
- Seri durumdan çıkarma özelliğini özniteliklerle yapılandırın.
Bu öğreticinin son örneğini takip etmek isterseniz indirebilirsiniz. İndirme yönergeleri için bkz . Örnekler ve Öğreticiler.
Önkoşullar
- .NET SDK 6.0 veya üzeri
- [Visual Studio Code (açık kaynak, platformlar arası düzenleyici) gibi bir kod düzenleyicisi. Örnek uygulamayı Windows, Linux veya macOS üzerinde ya da docker kapsayıcısında çalıştırabilirsiniz.
İstemci uygulamasını oluşturma
Bir komut istemi açın ve uygulamanız için yeni bir dizin oluşturun. Bunu geçerli dizin yapın.
Konsol penceresine aşağıdaki komutu girin:
dotnet new console --name WebAPIClient
Bu komut, temel bir "Merhaba Dünya" uygulaması için başlangıç dosyalarını oluşturur. Proje adı "WebAPIClient" şeklindedir.
"WebAPIClient" dizinine gidin ve uygulamayı çalıştırın.
cd WebAPIClient
dotnet run
dotnet run
uygulamanın ihtiyaç duyduğu tüm bağımlılıkları geri yüklemek için otomatik olarak çalışırdotnet restore
. Gerekirse de çalışırdotnet build
. Uygulama çıkışını"Hello, World!"
görmeniz gerekir. Uygulamayı durdurmak için terminalinizde Ctrl+C tuşlarına basın.
HTTP isteğinde bulunma
Bu uygulama, .NET Foundation şemsiyesi altındaki projeler hakkında bilgi almak için GitHub API'sini çağırır. Uç nokta şeklindedir https://api.github.com/orgs/dotnet/repos. Bilgileri almak için bir HTTP GET isteğinde bulunur. Tarayıcılar http GET istekleri de yapar, böylece hangi bilgileri alıp işleyebileceğinizi görmek için bu URL'yi tarayıcı adres çubuğuna yapıştırabilirsiniz.
HTTP istekleri yapmak için sınıfını HttpClient kullanın. HttpClient uzun süre çalışan API'leri için yalnızca zaman uyumsuz yöntemleri destekler. Bu nedenle aşağıdaki adımlar zaman uyumsuz bir yöntem oluşturur ve bunu Main yönteminden çağırır.
Program.cs
Dosyayı proje dizininizde açın ve içeriğini aşağıdakilerle değiştirin:await ProcessRepositoriesAsync(); static async Task ProcessRepositoriesAsync(HttpClient client) { }
Bu kod:
- deyimini
Console.WriteLine
, anahtar sözcüğünü kullanan bir çağrısıylaProcessRepositoriesAsync
await
değiştirir. - Boş
ProcessRepositoriesAsync
bir yöntem tanımlar.
- deyimini
Program
sınıfında, içeriği aşağıdaki C# ile değiştirerek istekleri ve yanıtları işlemek için kullanınHttpClient.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) { }
Bu kod:
- Tüm istekler için HTTP üst bilgilerini ayarlar:
Accept
JSON yanıtlarını kabul etmek için üst bilgi- Üst
User-Agent
bilgi. Bu üst bilgiler GitHub sunucu kodu tarafından denetlenmektedir ve GitHub'dan bilgi almak için gereklidir.
- Tüm istekler için HTTP üst bilgilerini ayarlar:
yönteminde
ProcessRepositoriesAsync
, .NET foundation kuruluşu altındaki tüm depoların listesini döndüren GitHub uç noktasını çağırın:static async Task ProcessRepositoriesAsync(HttpClient client) { var json = await client.GetStringAsync( "https://api.github.com/orgs/dotnet/repos"); Console.Write(json); }
Bu kod:
- Çağırma HttpClient.GetStringAsync(String) yönteminden döndürülen görevi bekler. Bu yöntem, belirtilen URI'ye bir HTTP GET isteği gönderir. Yanıtın gövdesi, görev tamamlandığında kullanılabilen olarak Stringdöndürülür.
- Yanıt dizesi
json
konsola yazdırılır.
Uygulamayı derleyin ve çalıştırın.
dotnet run
artık bir
await
işleç içerdiğindenProcessRepositoriesAsync
derleme uyarısı yok. Çıktı, JSON metninin uzun bir görüntüsüdür.
JSON Sonucunu Seri Durumdan Çıkarma
Aşağıdaki adımlar JSON yanıtını C# nesnelerine dönüştürür. JSON'ı System.Text.Json.JsonSerializer nesneler halinde seri durumdan çıkarabilmek için sınıfını kullanırsınız.
Repository.cs adlı bir dosya oluşturun ve aşağıdaki kodu ekleyin:
public record class Repository(string name);
Yukarıdaki kod, GitHub API'sinden döndürülen JSON nesnesini temsil eden bir sınıf tanımlar. Depo adlarının listesini görüntülemek için bu sınıfı kullanacaksınız.
Bir depo nesnesi için JSON onlarca özellik içerir, ancak yalnızca özelliği seri durumdan
name
çıkarılır. Seri hale getirici, hedef sınıfta eşleşme olmayan JSON özelliklerini otomatik olarak yoksayar. Bu özellik, büyük bir JSON paketindeki alanların yalnızca bir alt kümesiyle çalışan türler oluşturmayı kolaylaştırır.C# kuralı, özellik adlarının ilk harfini büyük harfe çevirir, ancak
name
buradaki özellik JSON'dakiyle tam olarak eşleştiğinden küçük harfle başlar. Daha sonra, JSON özellik adlarına uymayan C# özellik adlarının nasıl kullanılacağını göreceksiniz.JSON'ı C# nesnelerine dönüştürmek için seri hale getiriciyi kullanın. yöntemindeki çağrısının GetStringAsync(String)
ProcessRepositoriesAsync
yerine aşağıdaki satırları ekleyin:await using Stream stream = await client.GetStreamAsync("https://api.github.com/orgs/dotnet/repos"); var repositories = await JsonSerializer.DeserializeAsync<List<Repository>>(stream);
Güncelleştirilen kod ile GetStreamAsync(String)değiştirilirGetStringAsync(String). Bu seri hale getirici yöntemi, kaynağı olarak dize yerine bir akış kullanır.
için ilk bağımsız değişken JsonSerializer.DeserializeAsync<TValue>(Stream, JsonSerializerOptions, CancellationToken) bir
await
ifadedir.await
ifadeleri kodunuzda neredeyse her yerde görünebilir, ancak şimdiye kadar bunları yalnızca atama deyiminin bir parçası olarak gördünüz. ve diğer iki parametreJsonSerializerOptions
CancellationToken
isteğe bağlıdır ve kod parçacığında atlanır.DeserializeAsync
yöntemi geneldir, yani JSON metninden oluşturulması gereken nesne türleri için tür bağımsız değişkenleri sağlarsınız. Bu örnekte, başka bir genel nesne System.Collections.Generic.List<T>olan birList<Repository>
için seri durumdan çıkarıyorsunuz.List<T>
sınıfı bir nesne koleksiyonu depolar. tür bağımsız değişkeni, içindeList<T>
depolanan nesnelerin türünü bildirir. JSON metni bir depo nesneleri koleksiyonunu temsil ettiğinden tür bağımsız değişkeni kaydınızdırRepository
.Her deponun adını görüntülemek için kod ekleyin. Şu satırları değiştirin:
Console.Write(json);
aşağıdaki kodla:
foreach (var repo in repositories ?? Enumerable.Empty<Repository>()) Console.Write(repo.name);
Dosyanın en üstünde aşağıdaki
using
yönergeler bulunmalıdır:using System.Net.Http.Headers; using System.Text.Json;
Uygulamayı çalıştırın.
dotnet run
Çıktı, .NET Foundation'ın parçası olan depoların adlarının listesidir.
Seri durumdan çıkarma yapılandırma
Repository.cs dosyasında dosya içeriğini aşağıdaki C# ile değiştirin.
using System.Text.Json.Serialization; public record class Repository( [property: JsonPropertyName("name")] string Name);
Bu kod:
- Özelliğin
name
adını olarakName
değiştirir. - bu özelliğin JsonPropertyNameAttribute JSON'da nasıl görüneceğini belirtmek için öğesini ekler.
- Özelliğin
Program.cs dosyasında, özelliğin yeni büyük harf kullanımını kullanmak için kodu güncelleştirin
Name
:foreach (var repo in repositories) Console.Write(repo.Name);
Uygulamayı çalıştırın.
Çıkış aynıdır.
Kodu yeniden düzenleme
ProcessRepositoriesAsync
yöntemi zaman uyumsuz çalışmayı yapabilir ve depoların koleksiyonunu döndürebilir. bu yöntemi döndürecek Task<List<Repository>>
şekilde değiştirin ve konsola yazan kodu çağıranın yanına taşıyın.
sonucu nesne listesi olan bir görevi döndürmek için imzasını
ProcessRepositoriesAsync
Repository
değiştirin:static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
JSON yanıtını işledikten sonra depoları döndür:
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();
Bu yöntemi olarak
async
işaretlediğiniz için derleyici dönüş değeri için nesnesini oluştururTask<T>
.Program.cs dosyasını değiştirin ve sonuçları yakalamak için çağrısının
ProcessRepositoriesAsync
yerine aşağıdakini yazın ve her depo adını konsola yazın.var repositories = await ProcessRepositoriesAsync(client); foreach (var repo in repositories) Console.Write(repo.Name);
Uygulamayı çalıştırın.
Çıkış aynıdır.
Daha fazla özelliği seri durumdan çıkarma
Aşağıdaki adımlar, alınan JSON paketindeki daha fazla özelliği işlemek için kod ekler. Büyük olasılıkla her özelliği işlemek istemezsiniz, ancak birkaç özellik daha eklemek C# dilinin diğer özelliklerini gösterir.
sınıfının içeriğini
Repository
aşağıdakirecord
tanım ile değiştirin: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);
Uri ve
int
türleri, dize gösterimine ve bu gösterimden dönüştürmeye ilişkin yerleşik işlevlere sahiptir. JSON dize biçiminden bu hedef türlerine seri durumdan kaldırmak için ek kod gerekmez. JSON paketi hedef türe dönüştürülmeyen veriler içeriyorsa, serileştirme eylemi bir özel durum oluşturur.foreach
Özellik değerlerini görüntülemek için Program.cs dosyasındaki döngüsünü güncelleştirin: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(); }
Uygulamayı çalıştırın.
Liste artık ek özellikleri içerir.
Tarih özelliği ekleme
Son gönderme işleminin tarihi JSON yanıtında şu şekilde biçimlendirilir:
2016-02-08T21:27:00Z
Bu biçim Eşgüdümlü Evrensel Saat (UTC) içindir, bu nedenle seri durumdan çıkarmanın sonucu özelliği olan Kind bir DateTime değerdirUtc.
Saat diliminizde temsil edilen bir tarih ve saat almak için özel bir dönüştürme yöntemi yazmanız gerekir.
Repository.cs içinde, tarih ve saatin UTC gösterimi için bir özellik ve yerel saate dönüştürülen tarihi döndüren salt okunur
LastPush
bir özellik ekleyin; dosya aşağıdaki gibi görünmelidir: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(); }
LastPush
özelliği, erişimci içinget
ifade gövdeli bir üye kullanılarak tanımlanır. Aksesuar falan yokset
. Erişimcininset
atlanması, C# dilinde salt okunur özelliği tanımlamanın bir yoludur. (Evet, C# dilinde yalnızca yazma özellikleri oluşturabilirsiniz, ancak değerleri sınırlıdır.)Program.cs dosyasına başka bir çıkış deyimi ekleyin: yeniden:
Console.WriteLine($"Last push: {repo.LastPush}");
Uygulamanın tamamı aşağıdaki Program.cs dosyasına benzemelidir:
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(); }
Uygulamayı çalıştırın.
Çıkış, her depoya son gönderimin tarih ve saatini içerir.
Sonraki adımlar
Bu öğreticide, web istekleri yapan ve sonuçları ayrıştıran bir uygulama oluşturdunuz. Uygulama sürümünüz artık tamamlanmış örnekle eşleşmelidir.
JSON serileştirmeyi yapılandırma hakkında daha fazla bilgi için bkz. .NET'te JSON'ı seri hale getirme ve seri durumdan çıkarma (hazırlama ve seri durumdan çıkarma).