Bagikan melalui


Tutorial: Membuat permintaan di aplikasi konsol .NET menggunakan C#

Tutorial ini membuat aplikasi yang mengeluarkan permintaan HTTP ke layanan REST di GitHub. Aplikasi membaca informasi dalam format JSON dan mengubah JSON menjadi objek C#. Mengonversi dari objek JSON ke C# dikenal sebagai deserialisasi.

Tutorial ini menunjukkan cara:

  • Mengirim permintaan.
  • Melakukan deserialisasi respons JSON.
  • Mengonfigurasi deserialisasi dengan atribut.

Jika Anda lebih suka mengikuti sampel akhir untuk tutorial ini, Anda dapat mengunduhnya. Untuk petunjuk pengunduhan, lihat Sampel dan Tutorial.

Prasyarat

  • .NET SDK 6.0 atau yang lebih baru
  • Editor kode seperti [Visual Studio Code (editor lintas platform sumber terbuka). Anda dapat menjalankan aplikasi sampel di Windows, Linux, atau macOS, atau dalam kontainer Docker.

Buat aplikasi klien

  1. Buka perintah dan buat direktori baru untuk aplikasi Anda. Jadikan direktori baru tersebut direktori saat ini.

  2. Masukkan perintah berikut di jendela konsol:

    dotnet new console --name WebAPIClient
    

    Perintah ini membuat file starter untuk aplikasi dasar "Halo Dunia". Nama proyeknya adalah "WebAPIClient".

  3. Arahkan ke direktori "WebAPIClient", dan jalankan aplikasi.

    cd WebAPIClient
    
    dotnet run
    

    dotnet run secara otomatis menjalankan dotnet restore untuk memulihkan dependensi apa pun yang dibutuhkan aplikasi. Proyek tersebut juga menjalankan dotnet build jika diperlukan. Anda akan melihat output "Hello, World!"aplikasi . Di terminal Anda, tekan Ctrl+C untuk menghentikan aplikasi.

Buat permintaan HTTP

Aplikasi ini memanggil GitHub API untuk mendapatkan informasi tentang proyek di bawah payung .NET Foundation. Titik akhirnya adalah https://api.github.com/orgs/dotnet/repos. Untuk mengambil informasi, itu membuat permintaan HTTP GET. Browser juga membuat permintaan HTTP GET, sehingga Anda dapat menempelkan URL tersebut ke bilah alamat browser untuk melihat informasi apa yang akan Anda terima dan proses.

Gunakan kelas HttpClient untuk membuat permintaan. HttpClient hanya mendukung metode asinkron untuk API yang berjalan lama. Jadi langkah-langkah berikut membuat metode asinkron dan memanggilnya dari metode Utama.

  1. Program.cs Buka file di direktori proyek Anda dan ganti kontennya dengan yang berikut ini:

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

    Kode ini:

    • Mengganti pernyataan Console.WriteLine dengan panggilan ke ProcessRepositoriesAsync yang menggunakan kata kunci await.
    • Mendefinisikan metode kosong ProcessRepositoriesAsync .
  2. Program Di kelas , gunakan HttpClient untuk menangani permintaan dan respons, dengan mengganti konten dengan C#berikut.

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

    Kode ini:

    • Menyiapkan header HTTP untuk semua permintaan:
      • Header Accept untuk menerima tanggapan JSON
      • Header User-Agent. Header ini diperiksa oleh kode server GitHub dan diperlukan untuk mengambil informasi dari GitHub.
  3. Dalam metode ProcessRepositoriesAsync, panggil titik akhir GitHub yang mengembalikan daftar semua repositori di bawah organisasi .NET foundation:

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

    Kode ini:

    • Menunggu tugas yang dikembalikan dari metode panggilan HttpClient.GetStringAsync(String) . Metode ini mengirimkan permintaan HTTP GET ke URI yang ditentukan. Isi respons dikembalikan sebagai String, yang tersedia saat tugas selesai.
    • String json respons dicetak ke konsol.
  4. Bangun aplikasi dan jalankan.

    dotnet run
    

    Tidak ada peringatan build karena ProcessRepositoriesAsync sekarang berisi operator await. Outputnya adalah tampilan panjang teks JSON.

Deserialisasi Hasil JSON

Langkah-langkah berikut mengubah respons JSON menjadi objek C#. Anda menggunakan kelas System.Text.Json.JsonSerializer untuk membatalkan serialisasi JSON menjadi objek.

  1. Buat file bernama Repository.cs dan tambahkan kode berikut:

    public record class Repository(string name);
    

    Kode sebelumnya mendefinisikan kelas untuk mewakili objek JSON yang dikembalikan dari GitHub API. Anda akan menggunakan kelas ini untuk menampilkan daftar nama repositori.

    JSON untuk objek repositori berisi lusinan properti, tetapi hanya properti name yang akan dideserialisasi. Serializer secara otomatis mengabaikan properti JSON yang tidak cocok dengan kelas target. Fitur ini memudahkan untuk membuat jenis yang bekerja hanya dengan subset bidang dalam paket JSON yang besar.

    Konvensi C# adalah menggunakan huruf kapital pada huruf pertama dari nama properti , tetapi properti name di sini dimulai dengan huruf kecil karena sama persis dengan apa yang ada di JSON. Nanti Anda akan melihat cara menggunakan nama properti C# yang tidak cocok dengan nama properti JSON.

  2. Gunakan serializer untuk mengubah JSON menjadi objek C#. Ganti panggilan ke GetStringAsync(String) dalam metode ProcessRepositoriesAsync dengan baris berikut:

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

    Kode yang diperbarui menggantikan GetStringAsync(String) dengan GetStreamAsync(String). Metode serializer ini menggunakan aliran alih-alih string sebagai sumbernya.

    Argumen pertama untuk JsonSerializer.DeserializeAsync<TValue>(Stream, JsonSerializerOptions, CancellationToken) adalah ekspresi await. await ekspresi dapat muncul hampir di mana saja dalam kode Anda, meskipun hingga sekarang, Anda hanya melihatnya sebagai bagian dari pernyataan penugasan. Dua parameter lainnya, JsonSerializerOptions dan CancellationToken, bersifat opsional dan dihilangkan dalam cuplikan kode.

    Metode DeserializeAsync adalah generik, yang berarti Anda memberikan argumen jenis untuk jenis objek yang harus dibuat dari teks JSON. Dalam contoh ini, Anda melakukan deserializing ke List<Repository>, yang merupakan objek umum lainnya, a System.Collections.Generic.List<T>. Kelas List<T> menyimpan koleksi objek. Argumen jenis mendeklarasikan jenis objek yang disimpan di List<T>. Argumen jenis adalah rekaman Anda Repository , karena teks JSON mewakili kumpulan objek repositori.

  3. Tambahkan kode untuk menampilkan nama setiap repositori. Ganti baris yang berbunyi:

    Console.Write(json);
    

    dengan kode berikut:

    foreach (var repo in repositories ?? Enumerable.Empty<Repository>())
        Console.Write(repo.name);
    
  4. Arahan berikut using harus ada di bagian atas file:

    using System.Net.Http.Headers;
    using System.Text.Json;
    
  5. Menjalankan aplikasi.

    dotnet run
    

    Outputnya adalah daftar nama repositori yang merupakan bagian dari .NET Foundation.

Konfigurasi deserialisasi

  1. Di Repository.cs, ganti konten file dengan C#berikut.

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

    Kode ini:

    • Mengubah nama properti menjadi nameName.
    • JsonPropertyNameAttribute Menambahkan untuk menentukan bagaimana properti ini muncul di JSON.
  2. Di Program.cs, perbarui kode untuk menggunakan kapitalisasi baru dari properti Name :

    foreach (var repo in repositories)
       Console.Write(repo.Name);
    
  3. Menjalankan aplikasi.

    Outputnya sama.

Refaktor kode

Metode ProcessRepositoriesAsync dapat melakukan pekerjaan asinkron dan mengembalikan koleksi repositori. Ubah metode tersebut untuk mengembalikan Task<List<Repository>>, dan pindahkan kode yang menulis ke konsol di dekat pemanggilnya.

  1. Ubah tanda tangan ProcessRepositoriesAsync untuk mengembalikan tugas yang hasilnya berupa daftar objek Repository:

    static async Task<List<Repository>> ProcessRepositoriesAsync(HttpClient client)
    
  2. Kembalikan repositori setelah memproses respons JSON:

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

    Pengompilasi menghasilkan objek Task<T> untuk nilai kembalian karena Anda telah menandai metode ini sebagai async.

  3. Ubah file Program.cs , ganti panggilan ke ProcessRepositoriesAsync dengan yang berikut ini untuk mengambil hasilnya dan menulis setiap nama repositori ke konsol.

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

    Outputnya sama.

Deserialisasi lebih banyak properti

Langkah-langkah berikut menambahkan kode untuk memproses lebih banyak properti dalam paket JSON yang diterima. Anda mungkin tidak ingin memproses setiap properti, tetapi menambahkan beberapa properti lagi menunjukkan fitur lain dari C#.

  1. Ganti konten Repository kelas, dengan definisi berikut record :

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

    Jenis Uri dan int memiliki fungsionalitas bawaan untuk mengonversi ke dan dari representasi string. Tidak ada kode tambahan yang diperlukan untuk mendeserialisasi dari format string JSON ke jenis target tersebut. Jika paket JSON berisi data yang tidak dikonversi ke jenis target, tindakan serialisasi akan melemparkan pengecualian.

  2. Perbarui perulangan foreach dalam file Program.cs untuk menampilkan nilai properti:

    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. Menjalankan aplikasi.

    Daftar sekarang termasuk properti tambahan.

Tambahkan properti tanggal

Tanggal operasi pendorongan terakhir diformat dengan cara ini dalam respons JSON:

2016-02-08T21:27:00Z

Format ini untuk Waktu Universal Terkoordinasi (UTC), sehingga hasil deserialisasi adalah nilai DateTime yang properti Kind-nya adalah Utc.

Untuk mendapatkan tanggal dan waktu yang diwakili di zona waktu Anda, Anda harus menulis metode konversi kustom.

  1. Di Repository.cs, tambahkan properti untuk representasi UTC tanggal dan waktu dan properti baca-saja LastPush yang mengembalikan tanggal yang dikonversi ke waktu lokal, file akan terlihat seperti berikut ini:

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

    Properti LastPush didefinisikan menggunakan anggota bertubuh ekspresi untuk aksesor get. Tidak ada pengakses set. Menghilangkan pengakses set adalah salah satu cara untuk menentukan properti baca-saja di C#. (Ya, Anda dapat membuat properti tulis-saja di C#, tetapi nilainya terbatas.)

  2. Tambahkan pernyataan output lain di Program.cs: lagi:

    Console.WriteLine($"Last push: {repo.LastPush}");
    
  3. Aplikasi lengkap harus menyerupai file Program.cs berikut:

    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. Menjalankan aplikasi.

    Outputnya mencakup tanggal dan waktu pendorongan terakhir ke setiap repositori.

Langkah berikutnya

Dalam tutorial ini, Anda membuat aplikasi yang membuat permintaan web dan mengurai hasilnya. Versi aplikasi Anda sekarang harus cocok dengan sampel yang sudah selesai.

Pelajari selengkapnya tentang cara mengonfigurasi serialisasi JSON di Cara membuat serialisasi dan deserialisasi (marshal dan unmarshal) JSON di .NET.