Bagikan melalui


Memanggil API Web Dari Klien .NET (C#)

Konten ini untuk versi .NET sebelumnya. Pengembangan baru harus menggunakan ASP.NET Core. Untuk informasi selengkapnya tentang menggunakan ASP.NET Core Web API, lihat:

Unduh Proyek yang Selesai.

Tutorial ini menunjukkan cara memanggil API web dari aplikasi .NET, menggunakan System.Net.Http.HttpClient.

Dalam tutorial ini, aplikasi klien ditulis yang menggunakan API web berikut:

Tindakan Metode HTTP URI relatif
Mendapatkan produk berdasarkan ID GET /api/products/id
Membuat produk baru POST /api/products
Memperbarui produk PUT /api/products/id
Menghapus produk DELETE /api/products/id

Untuk mempelajari cara menerapkan API ini dengan ASP.NET Web API, lihat Membuat API Web yang Mendukung Operasi CRUD.

Untuk kesederhanaan, aplikasi klien dalam tutorial ini adalah aplikasi konsol Windows. HttpClient juga didukung untuk aplikasi Windows Phone dan Windows Store. Untuk informasi selengkapnya, lihat Menulis Kode Klien API Web untuk Beberapa Platform Menggunakan Pustaka Portabel

CATATAN: Jika Anda meneruskan URL dasar dan URI relatif sebagai nilai yang dikodekan secara permanen, perhatikan aturan untuk menggunakan HttpClient API. Properti HttpClient.BaseAddress harus diatur ke alamat dengan garis miring ke depan (/). Misalnya, saat meneruskan URI sumber daya yang dikodekan secara permanen ke HttpClient.GetAsync metode , jangan sertakan garis miring ke depan. Untuk mendapatkan Product berdasarkan ID:

  1. Set client.BaseAddress = new Uri("https://localhost:5001/");
  2. Minta .Product Contohnya,client.GetAsync<Product>("api/products/4");.

Membuat Aplikasi Konsol

Di Visual Studio, buat aplikasi konsol Windows baru bernama HttpClientSample dan tempelkan kode berikut:

using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace HttpClientSample
{
    public class Product
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }

    class Program
    {
        static HttpClient client = new HttpClient();

        static void ShowProduct(Product product)
        {
            Console.WriteLine($"Name: {product.Name}\tPrice: " +
                $"{product.Price}\tCategory: {product.Category}");
        }

        static async Task<Uri> CreateProductAsync(Product product)
        {
            HttpResponseMessage response = await client.PostAsJsonAsync(
                "api/products", product);
            response.EnsureSuccessStatusCode();

            // return URI of the created resource.
            return response.Headers.Location;
        }

        static async Task<Product> GetProductAsync(string path)
        {
            Product product = null;
            HttpResponseMessage response = await client.GetAsync(path);
            if (response.IsSuccessStatusCode)
            {
                product = await response.Content.ReadAsAsync<Product>();
            }
            return product;
        }

        static async Task<Product> UpdateProductAsync(Product product)
        {
            HttpResponseMessage response = await client.PutAsJsonAsync(
                $"api/products/{product.Id}", product);
            response.EnsureSuccessStatusCode();

            // Deserialize the updated product from the response body.
            product = await response.Content.ReadAsAsync<Product>();
            return product;
        }

        static async Task<HttpStatusCode> DeleteProductAsync(string id)
        {
            HttpResponseMessage response = await client.DeleteAsync(
                $"api/products/{id}");
            return response.StatusCode;
        }

        static void Main()
        {
            RunAsync().GetAwaiter().GetResult();
        }

        static async Task RunAsync()
        {
            // Update port # in the following line.
            client.BaseAddress = new Uri("http://localhost:64195/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

            try
            {
                // Create a new product
                Product product = new Product
                {
                    Name = "Gizmo",
                    Price = 100,
                    Category = "Widgets"
                };

                var url = await CreateProductAsync(product);
                Console.WriteLine($"Created at {url}");

                // Get the product
                product = await GetProductAsync(url.PathAndQuery);
                ShowProduct(product);

                // Update the product
                Console.WriteLine("Updating price...");
                product.Price = 80;
                await UpdateProductAsync(product);

                // Get the updated product
                product = await GetProductAsync(url.PathAndQuery);
                ShowProduct(product);

                // Delete the product
                var statusCode = await DeleteProductAsync(product.Id);
                Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }

            Console.ReadLine();
        }
    }
}

Kode sebelumnya adalah aplikasi klien lengkap.

RunAsync berjalan dan memblokir hingga selesai. Sebagian besar metode HttpClient adalah asinkron, karena mereka melakukan I/O jaringan. Semua tugas asinkron dilakukan di dalam RunAsync. Biasanya aplikasi tidak memblokir utas utama, tetapi aplikasi ini tidak mengizinkan interaksi apa pun.

static async Task RunAsync()
{
    // Update port # in the following line.
    client.BaseAddress = new Uri("http://localhost:64195/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));

    try
    {
        // Create a new product
        Product product = new Product
        {
            Name = "Gizmo",
            Price = 100,
            Category = "Widgets"
        };

        var url = await CreateProductAsync(product);
        Console.WriteLine($"Created at {url}");

        // Get the product
        product = await GetProductAsync(url.PathAndQuery);
        ShowProduct(product);

        // Update the product
        Console.WriteLine("Updating price...");
        product.Price = 80;
        await UpdateProductAsync(product);

        // Get the updated product
        product = await GetProductAsync(url.PathAndQuery);
        ShowProduct(product);

        // Delete the product
        var statusCode = await DeleteProductAsync(product.Id);
        Console.WriteLine($"Deleted (HTTP Status = {(int)statusCode})");

    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }

    Console.ReadLine();
}

Menginstal Pustaka Klien API Web

Gunakan NuGet Package Manager untuk menginstal paket Pustaka Klien API Web.

Dari menu Alat, pilih Pengelola Paket NuGet>Konsol Pengelola Paket. Di Package Manager Console (PMC), ketik perintah berikut:

Install-Package Microsoft.AspNet.WebApi.Client

Perintah sebelumnya menambahkan paket NuGet berikut ke proyek:

  • Microsoft.AspNet.WebApi.Client
  • Newtonsoft.Json

Newtonsoft.Json (juga dikenal sebagai Json.NET) adalah kerangka kerja JSON berkinerja tinggi populer untuk .NET.

Menambahkan Kelas Model

Periksa Product kelas :

public class Product
{
    public string Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

Kelas ini cocok dengan model data yang digunakan oleh API web. Aplikasi dapat menggunakan HttpClient untuk membaca Product instans dari respons HTTP. Aplikasi tidak harus menulis kode deserialisasi apa pun.

Membuat dan Menginisialisasi HttpClient

Periksa properti HttpClient statis:

static HttpClient client = new HttpClient();

HttpClient dimaksudkan untuk dibuat sekali dan digunakan kembali sepanjang masa pakai aplikasi. Kondisi berikut dapat mengakibatkan kesalahan SocketException :

  • Membuat instans HttpClient baru per permintaan.
  • Server di bawah beban berat.

Membuat instans HttpClient baru per permintaan dapat menghabiskan soket yang tersedia.

Kode berikut menginisialisasi instans HttpClient :

static async Task RunAsync()
{
    // Update port # in the following line.
    client.BaseAddress = new Uri("http://localhost:64195/");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));

Kode sebelumnya:

  • Mengatur URI dasar untuk permintaan HTTP. Ubah nomor port ke port yang digunakan di aplikasi server. Aplikasi tidak akan berfungsi kecuali port untuk aplikasi server digunakan.
  • Mengatur header Terima ke "application/json". Mengatur header ini memberi tahu server untuk mengirim data dalam format JSON.

Mengirim permintaan GET untuk mengambil sumber daya

Kode berikut mengirimkan permintaan GET untuk produk:

static async Task<Product> GetProductAsync(string path)
{
    Product product = null;
    HttpResponseMessage response = await client.GetAsync(path);
    if (response.IsSuccessStatusCode)
    {
        product = await response.Content.ReadAsAsync<Product>();
    }
    return product;
}

Metode GetAsync mengirimkan permintaan HTTP GET. Ketika metode selesai, metode mengembalikan HttpResponseMessage yang berisi respons HTTP. Jika kode status dalam respons adalah kode keberhasilan, isi respons berisi representasi JSON dari produk. Panggil ReadAsAsync untuk mendeserialisasi payload JSON ke Product instans. Metode ReadAsync bersifat asinkron karena isi respons dapat sangat besar.

HttpClient tidak memberikan pengecualian ketika respons HTTP berisi kode kesalahan. Sebaliknya, properti IsSuccessStatusCodesalah jika statusnya adalah kode kesalahan. Jika Anda lebih suka memperlakukan kode kesalahan HTTP sebagai pengecualian, panggil HttpResponseMessage.EnsureSuccessStatusCode pada objek respons. EnsureSuccessStatusCode memberikan pengecualian jika kode status berada di luar rentang 200–299. Perhatikan bahwa HttpClient dapat melemparkan pengecualian karena alasan lain — misalnya, jika waktu permintaan habis.

Media-Type Pemformat untuk Deserialisasi

Ketika ReadAsync dipanggil tanpa parameter, ReadAsync menggunakan sekumpulan formatter media default untuk membaca isi respons. Formatter default mendukung data yang dikodekan JSON, XML, dan Form-url.

Alih-alih menggunakan pemformat default, Anda dapat menyediakan daftar pemformat ke metode ReadAsasync . Menggunakan daftar pemformat berguna jika Anda memiliki pemformat jenis media kustom:

var formatters = new List<MediaTypeFormatter>() {
    new MyCustomFormatter(),
    new JsonMediaTypeFormatter(),
    new XmlMediaTypeFormatter()
};
resp.Content.ReadAsAsync<IEnumerable<Product>>(formatters);

Untuk informasi selengkapnya, lihat Media Formatters di ASP.NET Web API 2

Mengirim Permintaan POST untuk Membuat Sumber Daya

Kode berikut mengirimkan permintaan POST yang berisi Product instans dalam format JSON:

static async Task<Uri> CreateProductAsync(Product product)
{
    HttpResponseMessage response = await client.PostAsJsonAsync(
        "api/products", product);
    response.EnsureSuccessStatusCode();

    // return URI of the created resource.
    return response.Headers.Location;
}

Metode PostAsJsonAsync :

  • Menserialisasikan objek ke JSON.
  • Mengirim payload JSON dalam permintaan POST.

Jika permintaan berhasil:

  • Ini harus mengembalikan respons 201 (Dibuat).
  • Respons harus menyertakan URL sumber daya yang dibuat di header Lokasi.

Mengirim Permintaan PUT untuk Memperbarui Sumber Daya

Kode berikut mengirimkan permintaan PUT untuk memperbarui produk:

static async Task<Product> UpdateProductAsync(Product product)
{
    HttpResponseMessage response = await client.PutAsJsonAsync(
        $"api/products/{product.Id}", product);
    response.EnsureSuccessStatusCode();

    // Deserialize the updated product from the response body.
    product = await response.Content.ReadAsAsync<Product>();
    return product;
}

Metode PutAsJsonAsync berfungsi seperti PostAsJsonAsync, kecuali bahwa metode tersebut mengirim permintaan PUT alih-alih POST.

Mengirim Permintaan DELETE untuk Menghapus Sumber Daya

Kode berikut mengirimkan permintaan DELETE untuk menghapus produk:

static async Task<HttpStatusCode> DeleteProductAsync(string id)
{
    HttpResponseMessage response = await client.DeleteAsync(
        $"api/products/{id}");
    return response.StatusCode;
}

Seperti GET, permintaan DELETE tidak memiliki isi permintaan. Anda tidak perlu menentukan format JSON atau XML dengan DELETE.

Uji sampel

Untuk menguji aplikasi klien:

  1. Unduh dan jalankan aplikasi server. Verifikasi bahwa aplikasi server berfungsi. Misalnya, http://localhost:64195/api/products harus mengembalikan daftar produk.

  2. Atur URI dasar untuk permintaan HTTP. Ubah nomor port ke port yang digunakan di aplikasi server.

    static async Task RunAsync()
    {
        // Update port # in the following line.
        client.BaseAddress = new Uri("http://localhost:64195/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
    
  3. Jalankan aplikasi klien. Output berikut dihasilkan:

    Created at http://localhost:64195/api/products/4
    Name: Gizmo     Price: 100.0    Category: Widgets
    Updating price...
    Name: Gizmo     Price: 80.0     Category: Widgets
    Deleted (HTTP Status = 204)