Aracılığıyla paylaş


Öğretici: C# kullanarak bir .NET konsol uygulamasında HTTP istekleri yapma

Bu öğretici, GitHub'da bir REST hizmetine HTTP istekleri veren bir uygulama oluşturur. Uygulama bilgileri JSON biçiminde okur ve JSON'yi C# nesnelerine dönüştürür. JSON'dan C# nesnelerine dönüştürme, seri durumdan çıkarmaolarak bilinir.

Öğreticide şunların nasıl yapılacağını gösterilmektedir:

  • HTTP istekleri gönderin.
  • JSON yanıtlarını deseriyalize etme.
  • Seri durumdan çıkarma özelliğini özniteliklerle yapılandırın.

Bu eğiticideki son örnek ile birlikte ilerlemek isterseniz, indirebilirsiniz. İndirme yönergeleri için bkz. Örnekler ve Öğreticiler.

Önkoşullar

İstemci uygulamasını oluşturma

  1. Bir komut istemi açın ve uygulamanız için yeni bir dizin oluşturun. Geçerli dizin olarak seçin.

  2. 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.

  3. "WebAPIClient" dizinine gidin ve uygulamayı çalıştırın.

    cd WebAPIClient
    
    dotnet run
    

    dotnet run, uygulamanın ihtiyaç duyduğu bağımlılıkları geri yüklemek için dotnet restore otomatik olarak çalıştırır. Gerekirse dotnet build de çalışır. Uygulamanın "Hello, World!"çıkışını görmelisiniz. Uygulamayı durdurmak için terminalinizde Ctrl+C basın.

HTTP istekleri oluşturma

Bu uygulama, .NET Foundation şemsiyesi altındaki projeler hakkında bilgi almak için GitHub API çağırır. Uç nokta https://api.github.com/orgs/dotnet/repos. Bilgileri almak için bir HTTP GET isteğinde bulunur. Tarayıcılar ayrıca 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 isteklerinde bulunmak için HttpClient sınıfını kullanın. HttpClient, uzun süre çalışan API'leri için yalnızca asenkron yöntemleri destekler. Bu nedenle aşağıdaki adımlar, bir zaman uyumsuz yöntem oluşturur ve onu Main yönteminden çağırır.

  1. proje dizininizde Program.cs dosyasını açın ve içeriğini aşağıdakilerle değiştirin:

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

    Bu kod:

    • Console.WriteLine deyimini ProcessRepositoriesAsync anahtar sözcüğünü kullanan await çağrısıyla değiştirir.
    • Boş bir ProcessRepositoriesAsync yöntemi tanımlar.
  2. Program sınıfında, içeriği aşağıdaki C# ile değiştirerek istekleri ve yanıtları işlemek için bir HttpClient kullanın.

    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:
      • JSON yanıtlarının kabul edilmesine yönelik bir Accept başlığı
      • Bir User-Agent başlık. Bu üst bilgiler GitHub sunucu kodu tarafından denetlenmektedir ve GitHub'dan bilgi almak için gereklidir.
  3. ProcessRepositoriesAsync yönteminde, .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:

    • HttpClient.GetStringAsync(String) yöntemini çağırmaktan 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ılabilir bir Stringolarak geri döndürülür.
    • yanıt dizesi json konsola yazdırılır.
  4. Uygulamayı derleyin ve çalıştırın.

    dotnet run
    

    ProcessRepositoriesAsync artık bir await işleci içerdiğinden derleme uyarısı yok. Çıkış, JSON metninin uzun bir görüntüsüdür.

JSON Sonucunu Seri Durumdan Çıkarma

Aşağıdaki adımlar, verileri getirme ve işleme yaklaşımını basitleştirir. JSON sonuçlarını nesnelere GetFromJsonAsync getirmek ve seri durumdan çıkarmak için System.Net.Http.Json NuGet paketinin parçası📦 olan uzantı yöntemini kullanacaksınız.

  1. 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 Name özelliği seri durumdan çı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.

    Bir sonraki noktada kullanacağınız yöntemin özellik adları söz konusu olduğunda büyük/küçük harfe duyarsız olma avantajı olsa GetFromJsonAsync da, C# kuralı özellik adlarının ilk harfini büyük harfe çevirmedir.

  2. JSON'ı HttpClientJsonExtensions.GetFromJsonAsync getirmek ve C# nesnelerine dönüştürmek için yöntemini kullanın. GetStringAsync(String) yöntemindeki ProcessRepositoriesAsync çağrısını aşağıdaki satırlarla değiştirin:

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

    Güncelleştirilmiş kod, GetStringAsync(String) yerine HttpClientJsonExtensions.GetFromJsonAsyncalır.

    Yöntemin GetFromJsonAsync ilk bağımsız değişkeni bir await ifadedir. await ifadeler, şimdiye kadar yalnızca atama deyiminin bir parçası olarak görmüş olsanız bile kodunuzun hemen her yerinde görünebilir. Sonraki parametre requestUri isteğe bağlıdır ve nesne oluşturulurken client zaten belirtilmişse sağlanması gerekmez. Nesneye client istek göndermek için URI sağlamadınız, bu nedenle URI'yi şimdi belirttiniz. İsteğe bağlı son parametre CancellationToken olan , kod parçacığında atlanır.

    GetFromJsonAsync yöntemi geneldir, yani getirilen JSON metninden ne tür nesneler oluşturulacağı için tür bağımsız değişkenleri sağlarsınız. Bu örnekte, seri durumdan çıkardığınız obje, başka bir genel nesne olan List<Repository>olan bir System.Collections.Generic.List<T>'dır. List<T> sınıfı bir nesne koleksiyonu depolar. tür bağımsız değişkeni, List<T>'daki depolanan nesnelerin türünü bildirir. JSON metni bir depo nesneleri koleksiyonunu temsil ettiğinden, tür argümanınız Repository kaydınızdır.

  3. Her deponun adını görüntülemek için kod ekleyin. Şunu okuyan satırları değiştirin:

    Console.Write(json);
    

    aşağıdaki kodu kullanarak

    foreach (var repo in repositories ?? Enumerable.Empty<Repository>())
        Console.WriteLine(repo.Name);
    
  4. Dosyanın en üstünde aşağıdaki using yönergeleri bulunmalıdır:

    using System.Net.Http.Headers;
    using System.Net.Http.Json;
    
  5. Uygulamayı çalıştırın.

    dotnet run
    

    Çıktı, .NET Foundation'ın parçası olan depoların adlarının listesidir.

Kodu yeniden düzenleme

ProcessRepositoriesAsync yöntemi asenkron çalışmayı yapabilir ve depo koleksiyonunu döndürebilir. Task<List<Repository>>döndürmek için bu yöntemi değiştirin ve konsola yazan kodu çağıranın yakınına taşıyın.

  1. sonucu ProcessRepositoriesAsync nesnelerin listesi olan bir görevi döndürmek için Repository imzasını değiştirin:

    static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
    
  2. JSON yanıtını işledikten sonra depoları döndür:

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

    Bu yöntemi Task<T>olarak işaretlediğiniz için derleyici dönüş değeri için async nesnesini oluşturur.

  3. sonuçları yakalamak ve her depo adını konsola yazmak için çağrısını aşağıdakilerle değiştirerek ProcessRepositoriesAsync dosyasını değiştirin.

    var repositories = await ProcessRepositoriesAsync(client);
    
    foreach (var repo in repositories)
        Console.WriteLine(repo.Name);
    
  4. Uygulamayı çalıştırın.

    Çıktı aynı.

Daha fazla özelliği seri durumdan çıkarma

Aşağıdaki adımlarda, GitHub API'sinin döndürdiği JSON yükünden daha fazla özelliği işlemek için kodu genişleteceğiz. Büyük olasılıkla her özelliği işlemeniz gerekmez, ancak birkaç tane eklemek ek C# özelliklerini gösterir.

  1. sınıfının içeriğini Repository aşağıdaki record tanım ile değiştirin. System.Text.Json.Serialization ad alanını içe aktardığınızdan ve JSON alanlarını açıkça C# özelliklerine eşlemek amacıyla [JsonPropertyName] özniteliğini uyguladığınızdan emin olun.

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

    Uri ve int türleri, dize gösterimine ve dize gösteriminden dönüştürme için yerleşik işlevlere sahiptir. JSON dize biçiminden bu hedef türlere seri durumdan çıkarmak 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.

    JSON genellikle özellik adları için lowercase veya snake_case kullanır. ve html_url gibi pushed_at alanlar C# PascalCase adlandırma kurallarına uymaz. [JsonPropertyName] kullanımı, adları büyük ve küçük harf farklılıkları gösterse veya alt çizgi içerse bile bu JSON anahtarlarının ilgili C# özelliklerine doğru şekilde bağlanmasını sağlar. Bu yaklaşım, C# dilinde PascalCase özellik adlarına izin verirken, tahmin edilebilir ve kararlı deserializasyon garanti eder. Ayrıca, GetFromJsonAsync yöntemi özellik adlarını eşleştirirken case-insensitive olduğundan, başka bir dönüştürme gerekmez.

  2. özellik değerlerini görüntülemek için foreach 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();
    }
    
  3. 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 bu şekilde biçimlendirilir:

2016-02-08T21:27:00Z

Bu format Koordine Evrensel Zaman (UTC) içindir, bu nedenle seri durumdan çıkarmanın sonucu, DateTime özelliği Kindolan bir Utc değeridir.

Saat diliminizde gösterilen bir tarih ve saati almak için özel bir dönüştürme yöntemi yazmanız gerekir.

  1. Repository.csiç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 bir LastPush özelliği ekleyin; dosya aşağıdaki gibi görünmelidir:

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

    LastPush özelliği, erişimcisi için get kullanılarak tanımlanır. set aksesuarı yok. set erişimcisinin atlanması, C# dilinde salt okunur özelliğini tanımlamanın bir yoludur. (Evet, C# dilinde salt yazma özellikleri oluşturabilirsiniz, ancak değerleri sınırlıdır.)

  2. Program.csiçine başka bir çıkış deyimi ekleyin: tekrar:

    Console.WriteLine($"Last push: {repo.LastPush}");
    
  3. Uygulamanın tamamı aşağıdaki Program.cs dosyasına benzemelidir:

    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. Uygulamayı çalıştırın.

    Çıkış, her depoya yapılan son gönderimin hem tarihini hem de 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ış örnekile eşleşmelidir.

.NET içinde JSON'u serileştirme ve deserileştirme (marshal ve unmarshal) adımlarını öğrenmek içinJSON serileştirmesini yapılandırma başlığına bakın.