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:
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:
- Set
client.BaseAddress = new Uri("https://localhost:5001/");
- 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:
Unduh dan jalankan aplikasi server. Verifikasi bahwa aplikasi server berfungsi. Misalnya,
http://localhost:64195/api/products
harus mengembalikan daftar produk.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"));
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)