Membuat permintaan HTTP dengan kelas HttpClient
Dalam artikel ini, Anda mempelajari cara membuat permintaan HTTP dan menangani respons dengan kelas HttpClient
.
Penting
Semua contoh permintaan HTTP dalam artikel ini menargetkan salah satu URL berikut:
- https://jsonplaceholder.typicode.com: Situs yang menyediakan platform API palsu gratis untuk pengujian dan prototipe.
- https://www.example.com: Domain yang tersedia untuk digunakan dalam contoh ilustrasi dalam dokumen.
Titik akhir HTTP biasanya mengembalikan data JavaScript Object Notation (JSON), tetapi tidak selalu. Untuk kenyamanan, paket System.Net.Http.Json NuGet opsional menyediakan beberapa metode ekstensi untuk objek HttpClient
dan HttpContent
yang melakukan serialisasi dan deserialisasi otomatis dengan menggunakan paket 📦 System.Text.Json NuGet. Contoh dalam artikel ini menyoroti tempat-tempat di mana ekstensi ini tersedia.
Petunjuk
Semua kode sumber yang direferensikan dalam artikel ini tersedia di GitHub: .NET Docs repositori.
Membuat objek HttpClient
Sebagian besar contoh dalam artikel ini menggunakan kembali instans HttpClient
yang sama, sehingga Anda dapat mengonfigurasi instans sekali dan menggunakannya untuk contoh yang tersisa. Untuk membuat objek HttpClient
, gunakan konstruktor kelas HttpClient
. Untuk informasi selengkapnya, lihat Panduan untuk menggunakan HttpClient.
// HttpClient lifecycle management best practices:
// https://learn.microsoft.com/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use
private static HttpClient sharedClient = new()
{
BaseAddress = new Uri("https://jsonplaceholder.typicode.com"),
};
Kode menyelesaikan tugas-tugas berikut:
- Buat instans
HttpClient
baru sebagai variabelstatic
. Menurut panduan , pendekatan yang direkomendasikan adalah menggunakan kembali instansHttpClient
selama siklus hidup aplikasi. - Atur properti HttpClient.BaseAddress ke
"https://jsonplaceholder.typicode.com"
.
Instans HttpClient
ini menggunakan alamat dasar untuk membuat permintaan berikutnya. Untuk menerapkan konfigurasi lain, pertimbangkan API berikut:
- Atur properti HttpClient.DefaultRequestHeaders.
- Terapkan properti HttpClient.Timeout yang bukan default.
- Tentukan properti HttpClient.DefaultRequestVersion.
Petunjuk
Atau, Anda dapat membuat instans HttpClient
dengan pola pabrik yang memungkinkan Anda mengonfigurasi sejumlah klien dan memanfaatkannya sebagai layanan injeksi dependensi. Untuk informasi selengkapnya, lihat penyedia klien HTTP dengan .NET.
Membuat permintaan HTTP
Untuk membuat permintaan HTTP, Anda memanggil salah satu metode API berikut:
Metode HTTP | API |
---|---|
GET |
HttpClient.GetAsync |
GET |
HttpClient.GetByteArrayAsync |
GET |
HttpClient.GetStreamAsync |
GET |
HttpClient.GetStringAsync |
POST |
HttpClient.PostAsync |
PUT |
HttpClient.PutAsync |
PATCH |
HttpClient.PatchAsync |
DELETE |
HttpClient.DeleteAsync |
†USER SPECIFIED |
HttpClient.SendAsync |
†Permintaan
USER SPECIFIED
menunjukkan bahwa metodeSendAsync
menerima objek HttpMethod yang valid.
Peringatan
Membuat permintaan HTTP dianggap sebagai pekerjaan terikat I/O jaringan. Metode HttpClient.Send sinkron ada, tetapi rekomendasinya adalah menggunakan API asinkron sebagai gantinya, kecuali Anda memiliki alasan yang baik untuk tidak.
Catatan
Saat menargetkan perangkat Android (seperti dengan pengembangan .NET MAUI), Anda harus menambahkan definisi android:usesCleartextTraffic="true"
ke bagian <application></application>
di file AndroidManifest.xml. Pengaturan ini memungkinkan lalu lintas teks jelas, seperti permintaan HTTP, yang dinonaktifkan secara default karena kebijakan keamanan Android. Pertimbangkan contoh pengaturan XML berikut:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:usesCleartextTraffic="true"></application>
<!-- omitted for brevity -->
</manifest>
Untuk informasi selengkapnya, lihat Mengaktifkan lalu lintas teks-jelas jaringan untuk domain localhost.
Memahami konten HTTP
HttpContent Jenis ini digunakan untuk mewakili isi entitas HTTP dan header konten yang sesuai. Untuk metode HTTP (atau metode permintaan) yang memerlukan isi (POST
, PUT
, PATCH
), Anda menggunakan kelas HttpContent untuk menentukan isi permintaan. Sebagian besar contoh menunjukkan cara menyiapkan StringContent subkelas dengan payload JSON, tetapi subkelas lain ada untuk jenis konten yang berbeda (MIME).
- ByteArrayContent: Menyediakan konten HTTP berdasarkan array byte.
-
FormUrlEncodedContent: Menyediakan konten HTTP untuk pasangan nama/nilai yang dikodekan dengan menggunakan jenis MIME
"application/x-www-form-urlencoded"
. - JsonContent: Menyediakan konten HTTP berdasarkan JSON.
-
MultipartContent: Menyediakan kumpulan objek HttpContent yang diserialisasikan dengan menggunakan spesifikasi jenis MIME
"multipart/*"
. -
MultipartFormDataContent: Menyediakan kontainer untuk konten yang dikodekan dengan menggunakan jenis
"multipart/form-data"
MIME. - ReadOnlyMemoryContent: Menyediakan konten HTTP berdasarkan nilai ReadOnlyMemory<T>.
- StreamContent: Menyediakan konten HTTP berdasarkan aliran.
- StringContent: Menyediakan konten HTTP berdasarkan string.
Kelas HttpContent
juga digunakan untuk mewakili isi respons kelas HttpResponseMessage, yang dapat diakses di properti HttpResponseMessage.Content.
Menggunakan permintaan HTTP GET
Permintaan GET
tidak boleh mengirim isi. Permintaan ini digunakan (seperti nama metode menunjukkan) untuk mengambil (atau mendapatkan) data dari sumber daya. Untuk membuat permintaan GET
HTTP yang diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.GetAsync:
static async Task GetAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.GetAsync("todos/3");
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output:
// GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1
// {
// "userId": 1,
// "id": 3,
// "title": "fugiat veniam minus",
// "completed": false
// }
}
Kode menyelesaikan tugas-tugas berikut:
- Buat permintaan
GET
ke endpoint"https://jsonplaceholder.typicode.com/todos/3"
. - Pastikan respons berhasil.
- Tulis detail permintaan ke konsol.
- Baca isi respons sebagai string.
- Tulis isi respons JSON ke konsol.
Metode WriteRequestToConsole
adalah ekstensi kustom yang bukan bagian dari kerangka kerja. Jika Anda ingin tahu tentang implementasinya, pertimbangkan kode C# berikut:
static class HttpResponseMessageExtensions
{
internal static void WriteRequestToConsole(this HttpResponseMessage response)
{
if (response is null)
{
return;
}
var request = response.RequestMessage;
Console.Write($"{request?.Method} ");
Console.Write($"{request?.RequestUri} ");
Console.WriteLine($"HTTP/{request?.Version}");
}
}
Fungsionalitas ini digunakan untuk menulis detail permintaan ke konsol dalam formulir berikut:
<HTTP Request Method> <Request URI> <HTTP/Version>
Sebagai contoh, permintaan GET
ke titik akhir "https://jsonplaceholder.typicode.com/todos/3"
menghasilkan pesan berikut:
GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1
Membuat permintaan HTTP GET dari JSON
Titik akhir https://jsonplaceholder.typicode.com/todos mengembalikan array JSON dari objek Todo
. Struktur JSON mereka berbentuk sebagai berikut:
[
{
"userId": 1,
"id": 1,
"title": "example title",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "another example title",
"completed": true
},
]
Objek C# Todo
didefinisikan sebagai berikut:
public record class Todo(
int? UserId = null,
int? Id = null,
string? Title = null,
bool? Completed = null);
Ini adalah jenis record class
, dengan properti opsional Id
, Title
, Completed
, dan UserId
. Untuk informasi selengkapnya tentang jenisnya record
, lihat Pengenalan jenis rekaman di C#. Untuk secara otomatis mendeserialisasi permintaan GET
ke dalam objek C# yang ditik dengan kuat, gunakan metode ekstensi GetFromJsonAsync yang merupakan bagian dari paket 📦 System.Net.Http.Json NuGet.
static async Task GetFromJsonAsync(HttpClient httpClient)
{
var todos = await httpClient.GetFromJsonAsync<List<Todo>>(
"todos?userId=1&completed=false");
Console.WriteLine("GET https://jsonplaceholder.typicode.com/todos?userId=1&completed=false HTTP/1.1");
todos?.ForEach(Console.WriteLine);
Console.WriteLine();
// Expected output:
// GET https://jsonplaceholder.typicode.com/todos?userId=1&completed=false HTTP/1.1
// Todo { UserId = 1, Id = 1, Title = delectus aut autem, Completed = False }
// Todo { UserId = 1, Id = 2, Title = quis ut nam facilis et officia qui, Completed = False }
// Todo { UserId = 1, Id = 3, Title = fugiat veniam minus, Completed = False }
// Todo { UserId = 1, Id = 5, Title = laboriosam mollitia et enim quasi adipisci quia provident illum, Completed = False }
// Todo { UserId = 1, Id = 6, Title = qui ullam ratione quibusdam voluptatem quia omnis, Completed = False }
// Todo { UserId = 1, Id = 7, Title = illo expedita consequatur quia in, Completed = False }
// Todo { UserId = 1, Id = 9, Title = molestiae perspiciatis ipsa, Completed = False }
// Todo { UserId = 1, Id = 13, Title = et doloremque nulla, Completed = False }
// Todo { UserId = 1, Id = 18, Title = dolorum est consequatur ea mollitia in culpa, Completed = False }
}
Kode menyelesaikan tugas-tugas berikut:
Buat permintaan
GET
ke"https://jsonplaceholder.typicode.com/todos?userId=1&completed=false"
.String kueri mewakili kriteria pemfilteran untuk permintaan. Ketika perintah berhasil, respons secara otomatis dideserialisasi ke dalam objek
List<Todo>
.Tulis detail permintaan ke konsol, bersama dengan setiap objek
Todo
.
Menggunakan permintaan HTTP POST
Permintaan POST
mengirim data ke server untuk diproses. Header Content-Type
permintaan menandakan jenis MIME yang dikirimkan oleh body. Untuk membuat permintaan POST
HTTP yang diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.PostAsync:
static async Task PostAsync(HttpClient httpClient)
{
using StringContent jsonContent = new(
JsonSerializer.Serialize(new
{
userId = 77,
id = 1,
title = "write code sample",
completed = false
}),
Encoding.UTF8,
"application/json");
using HttpResponseMessage response = await httpClient.PostAsync(
"todos",
jsonContent);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output:
// POST https://jsonplaceholder.typicode.com/todos HTTP/1.1
// {
// "userId": 77,
// "id": 201,
// "title": "write code sample",
// "completed": false
// }
}
Kode menyelesaikan tugas-tugas berikut:
- Siapkan instans StringContent dengan isi JSON permintaan (jenis MIME
"application/json"
). - Buat permintaan
POST
ke endpoint"https://jsonplaceholder.typicode.com/todos"
. - Pastikan respons berhasil dan tulis detail permintaan ke konsol.
- Tulis isi respons sebagai string ke konsol.
Membuat permintaan HTTP POST sebagai JSON
Untuk secara otomatis menserialisasikan POST
argumen permintaan dan mendeserialisasi respons ke dalam objek C# yang ditik dengan kuat, gunakan PostAsJsonAsync metode ekstensi yang merupakan bagian dari paket System.Net.Http.Json NuGet.
static async Task PostAsJsonAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.PostAsJsonAsync(
"todos",
new Todo(UserId: 9, Id: 99, Title: "Show extensions", Completed: false));
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var todo = await response.Content.ReadFromJsonAsync<Todo>();
Console.WriteLine($"{todo}\n");
// Expected output:
// POST https://jsonplaceholder.typicode.com/todos HTTP/1.1
// Todo { UserId = 9, Id = 201, Title = Show extensions, Completed = False }
}
Kode menyelesaikan tugas-tugas berikut:
- Serialisasi instans
Todo
sebagai JSON dan buat permintaanPOST
ke titik akhir"https://jsonplaceholder.typicode.com/todos"
. - Pastikan respons berhasil dan tulis detail permintaan ke konsol.
- Deserialisasi body respons menjadi instance
Todo
dan cetak objekTodo
ke konsol.
Menggunakan permintaan HTTP PUT
Metode permintaan PUT
mengganti sumber daya yang ada atau membuat yang baru dengan menggunakan payload isi permintaan. Untuk membuat permintaan PUT
HTTP yang diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.PutAsync:
static async Task PutAsync(HttpClient httpClient)
{
using StringContent jsonContent = new(
JsonSerializer.Serialize(new
{
userId = 1,
id = 1,
title = "foo bar",
completed = false
}),
Encoding.UTF8,
"application/json");
using HttpResponseMessage response = await httpClient.PutAsync(
"todos/1",
jsonContent);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output:
// PUT https://jsonplaceholder.typicode.com/todos/1 HTTP/1.1
// {
// "userId": 1,
// "id": 1,
// "title": "foo bar",
// "completed": false
// }
}
Kode menyelesaikan tugas-tugas berikut:
- Siapkan instans StringContent dengan isi JSON permintaan (jenis MIME
"application/json"
). - Buat permintaan
PUT
ke endpoint"https://jsonplaceholder.typicode.com/todos/1"
. - Pastikan respons berhasil dan tulis detail permintaan dengan isi respons JSON ke konsol.
Membuat permintaan HTTP PUT sebagai JSON
Untuk secara otomatis menserialisasikan PUT
argumen permintaan dan mendeserialisasi respons ke dalam objek C# yang ditik dengan kuat, gunakan PutAsJsonAsync metode ekstensi yang merupakan bagian dari paket System.Net.Http.Json NuGet.
static async Task PutAsJsonAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.PutAsJsonAsync(
"todos/5",
new Todo(Title: "partially update todo", Completed: true));
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var todo = await response.Content.ReadFromJsonAsync<Todo>();
Console.WriteLine($"{todo}\n");
// Expected output:
// PUT https://jsonplaceholder.typicode.com/todos/5 HTTP/1.1
// Todo { UserId = , Id = 5, Title = partially update todo, Completed = True }
}
Kode menyelesaikan tugas-tugas berikut:
- Serialisasi instans
Todo
sebagai JSON dan buat permintaanPUT
ke titik akhir"https://jsonplaceholder.typicode.com/todos/5"
. - Pastikan respons berhasil dan tulis detail permintaan ke konsol.
- Deserialisasi isi respons ke dalam instans
Todo
dan tulis objekTodo
ke konsol.
Gunakan permintaan PATCH HTTP
Permintaan PATCH
adalah pembaruan parsial ke sumber daya yang ada. Permintaan ini tidak membuat sumber daya baru dan tidak dimaksudkan untuk menggantikan sumber daya yang ada. Sebaliknya, metode ini hanya memperbarui sebagian sumber daya. Untuk membuat permintaan PATCH
HTTP yang diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.PatchAsync:
static async Task PatchAsync(HttpClient httpClient)
{
using StringContent jsonContent = new(
JsonSerializer.Serialize(new
{
completed = true
}),
Encoding.UTF8,
"application/json");
using HttpResponseMessage response = await httpClient.PatchAsync(
"todos/1",
jsonContent);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output
// PATCH https://jsonplaceholder.typicode.com/todos/1 HTTP/1.1
// {
// "userId": 1,
// "id": 1,
// "title": "delectus aut autem",
// "completed": true
// }
}
Kode menyelesaikan tugas-tugas berikut:
- Siapkan instans StringContent dengan isi JSON permintaan (jenis MIME
"application/json"
). - Buat permintaan
PATCH
ke endpoint"https://jsonplaceholder.typicode.com/todos/1"
. - Pastikan respons berhasil dan tulis detail permintaan dengan isi respons JSON ke konsol.
Tidak ada metode ekstensi untuk PATCH
permintaan dalam System.Net.Http.Json
paket NuGet.
Menggunakan permintaan HTTP DELETE
Permintaan DELETE
menghapus sumber daya yang ada dan permintaan tersebut idempoten, tetapi tidak aman. Beberapa permintaan DELETE
ke sumber daya yang sama menghasilkan hasil yang sama, tetapi permintaan memengaruhi status sumber daya. Untuk membuat permintaan DELETE
HTTP yang diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.DeleteAsync:
static async Task DeleteAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.DeleteAsync("todos/1");
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output
// DELETE https://jsonplaceholder.typicode.com/todos/1 HTTP/1.1
// {}
}
Kode menyelesaikan tugas-tugas berikut:
- Buat permintaan
DELETE
ke endpoint"https://jsonplaceholder.typicode.com/todos/1"
. - Pastikan respons berhasil dan tulis detail permintaan ke konsol.
Petunjuk
Respons terhadap permintaan DELETE
(seperti permintaan PUT
) mungkin atau mungkin tidak menyertakan isi.
Menjelajahi permintaan HTTP HEAD
Permintaan HEAD
ini mirip dengan permintaan GET
. Alih-alih mengembalikan sumber daya, permintaan ini hanya mengembalikan header yang terkait dengan sumber daya. Respon terhadap permintaan HEAD
tidak mengembalikan badan. Untuk membuat permintaan HTTP HEAD
dengan diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.SendAsync dengan menetapkan jenis HttpMethod ke HttpMethod.Head
:
static async Task HeadAsync(HttpClient httpClient)
{
using HttpRequestMessage request = new(
HttpMethod.Head,
"https://www.example.com");
using HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
foreach (var header in response.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
Console.WriteLine();
// Expected output:
// HEAD https://www.example.com/ HTTP/1.1
// Accept-Ranges: bytes
// Age: 550374
// Cache-Control: max-age=604800
// Date: Wed, 10 Aug 2022 17:24:55 GMT
// ETag: "3147526947"
// Server: ECS, (cha / 80E2)
// X-Cache: HIT
}
Kode menyelesaikan tugas-tugas berikut:
- Buat permintaan
HEAD
ke endpoint"https://www.example.com/"
. - Pastikan respons berhasil dan tulis detail permintaan ke konsol.
- Ulangi semua header respons dan tulis setiap header ke konsol.
Menjelajahi permintaan HTTP OPTIONS
Permintaan OPTIONS
digunakan untuk mengidentifikasi metode HTTP mana yang didukung server atau titik akhir. Untuk membuat permintaan HTTP OPTIONS
dengan diberikan instans HttpClient
dan objek Uri, gunakan metode HttpClient.SendAsync dengan menetapkan jenis HttpMethod ke HttpMethod.Options
:
static async Task OptionsAsync(HttpClient httpClient)
{
using HttpRequestMessage request = new(
HttpMethod.Options,
"https://www.example.com");
using HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
foreach (var header in response.Content.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
Console.WriteLine();
// Expected output
// OPTIONS https://www.example.com/ HTTP/1.1
// Allow: OPTIONS, GET, HEAD, POST
// Content-Type: text/html; charset=utf-8
// Expires: Wed, 17 Aug 2022 17:28:42 GMT
// Content-Length: 0
}
Kode menyelesaikan tugas-tugas berikut:
- Kirim permintaan HTTP
OPTIONS
ke titik akhir"https://www.example.com/"
. - Pastikan respons berhasil dan tulis detail permintaan ke konsol.
- Ulangi semua header konten respons dan tulis setiap header ke konsol.
Menjelajahi permintaan HTTP TRACE
Permintaan TRACE
dapat berguna untuk debugging karena menyediakan pemantulan kembali pada tingkat aplikasi dari pesan permintaan. Untuk membuat permintaan TRACE
HTTP, buat HttpRequestMessage dengan menggunakan jenis HttpMethod.Trace
:
using HttpRequestMessage request = new(
HttpMethod.Trace,
"{ValidRequestUri}");
Perhatian
Tidak semua server HTTP mendukung metode HTTP TRACE
. Metode ini dapat mengekspos kerentanan keamanan jika digunakan secara tidak bijak. Untuk informasi selengkapnya, lihat Proyek Keamanan Aplikasi Web Terbuka (OWASP): Cross Site Tracing.
Menangani respons HTTP
Saat Anda menangani respons HTTP, Anda berinteraksi dengan jenis HttpResponseMessage. Beberapa anggota digunakan untuk mengevaluasi validitas respons. Kode status HTTP tersedia di properti HttpResponseMessage.StatusCode.
Misalkan Anda mengirimkan permintaan saat menggunakan sebuah instance klien.
using HttpResponseMessage response = await httpClient.SendAsync(request);
Untuk memastikan response
adalah/berada pada OK
(kode status HTTP 200), Anda dapat mengevaluasi nilainya seperti yang ditunjukkan dalam contoh berikut:
if (response is { StatusCode: HttpStatusCode.OK })
{
// Omitted for brevity...
}
Ada kode status HTTP lainnya yang mewakili respons yang berhasil, seperti CREATED
(kode status HTTP 201), ACCEPTED
(kode status HTTP 202), NO CONTENT
(kode status HTTP 204), dan RESET CONTENT
(kode status HTTP 205). Anda dapat menggunakan HttpResponseMessage.IsSuccessStatusCode properti untuk mengevaluasi kode-kode ini juga, yang memastikan bahwa kode status respons berada dalam rentang 200-299:
if (response.IsSuccessStatusCode)
{
// Omitted for brevity...
}
Jika Anda perlu memiliki kerangka kerja yang melemparkan kesalahan HttpRequestException, Anda dapat memanggil metode HttpResponseMessage.EnsureSuccessStatusCode():
response.EnsureSuccessStatusCode();
Kode ini menampilkan kesalahan HttpRequestException
jika kode status respons tidak berada dalam rentang 200-299.
Menjelajahi respons konten http yang valid
Dengan respons yang valid, Anda dapat mengakses isi respons dengan menggunakan properti Content. Badan tersedia sebagai instans HttpContent, yang dapat Anda gunakan untuk mengakses badan sebagai stream, array byte, atau string.
Kode berikut menggunakan objek responseStream
untuk membaca isi respons:
await using Stream responseStream =
await response.Content.ReadAsStreamAsync();
Anda dapat menggunakan objek yang berbeda untuk membaca isi respons. Gunakan objek responseByteArray
untuk membaca isi respons:
byte[] responseByteArray = await response.Content.ReadAsByteArrayAsync();
Gunakan objek responseString
untuk membaca isi respons:
string responseString = await response.Content.ReadAsStringAsync();
Ketika Anda mengetahui titik akhir HTTP mengembalikan JSON, Anda dapat mendeserialisasi isi respons ke dalam objek C# yang valid dengan menggunakan paket System.Net.Http.Json NuGet:
T? result = await response.Content.ReadFromJsonAsync<T>();
Dalam kode ini, nilai result
adalah isi respons yang dideserialisasi sebagai jenis T
.
Gunakan penanganan kesalahan HTTP
Ketika permintaan HTTP gagal, sistem melemparkan objek HttpRequestException. Menangkap pengecualian saja mungkin tidak cukup. Ada pengecualian potensial lain yang mungkin ingin Anda pertimbangkan untuk ditangani. Misalnya, kode panggilan mungkin menggunakan token pembatalan yang dibatalkan sebelum permintaan selesai. Dalam skenario ini, Anda dapat menangkap kesalahan TaskCanceledException:
using var cts = new CancellationTokenSource();
try
{
// Assuming:
// httpClient.Timeout = TimeSpan.FromSeconds(10)
using var response = await httpClient.GetAsync(
"http://localhost:5001/sleepFor?seconds=100", cts.Token);
}
catch (OperationCanceledException ex) when (cts.IsCancellationRequested)
{
// When the token has been canceled, it is not a timeout.
Console.WriteLine($"Canceled: {ex.Message}");
}
Demikian juga, ketika Anda membuat permintaan HTTP, jika server tidak merespons sebelum nilai HttpClient.Timeout terlampaui, pengecualian yang sama akan dilemparkan. Dalam skenario ini, Anda dapat mengidentifikasi bahwa time-out terjadi dengan mengevaluasi properti Exception.InnerException saat menangkap kesalahan TaskCanceledException.
try
{
// Assuming:
// httpClient.Timeout = TimeSpan.FromSeconds(10)
using var response = await httpClient.GetAsync(
"http://localhost:5001/sleepFor?seconds=100");
}
catch (OperationCanceledException ex) when (ex.InnerException is TimeoutException tex)
{
Console.WriteLine($"Timed out: {ex.Message}, {tex.Message}");
}
Dalam kode, ketika pengecualian internal adalah tipe TimeoutException, maka terjadi batas waktu dan token pembatalan tidak membatalkan permintaan.
Untuk mengevaluasi kode status HTTP saat Anda menangkap objek HttpRequestException, Anda dapat mengevaluasi properti HttpRequestException.StatusCode:
try
{
// Assuming:
// httpClient.Timeout = TimeSpan.FromSeconds(10)
using var response = await httpClient.GetAsync(
"http://localhost:5001/doesNotExist");
response.EnsureSuccessStatusCode();
}
catch (HttpRequestException ex) when (ex is { StatusCode: HttpStatusCode.NotFound })
{
// Handle 404
Console.WriteLine($"Not found: {ex.Message}");
}
Dalam kode, metode EnsureSuccessStatusCode() dipanggil untuk melemparkan pengecualian jika respons tidak berhasil. Properti HttpRequestException.StatusCode kemudian dievaluasi untuk menentukan apakah responsnya adalah 404
(kode status HTTP 404). Ada beberapa metode pembantu pada objek HttpClient
yang secara implisit memanggil metode EnsureSuccessStatusCode
atas nama Anda.
Untuk penanganan kesalahan HTTP, pertimbangkan API berikut:
- metode HttpClient.GetByteArrayAsync
- metode HttpClient.GetStreamAsync
- metode HttpClient.GetStringAsync
Petunjuk
Semua metode HttpClient
digunakan untuk membuat permintaan HTTP yang tidak mengembalikan jenis HttpResponseMessage
secara implisit memanggil metode EnsureSuccessStatusCode
atas nama Anda.
Saat Anda memanggil metode ini, Anda dapat menangani objek HttpRequestException
dan mengevaluasi properti HttpRequestException.StatusCode untuk menentukan kode status HTTP respons:
try
{
// These extension methods will throw HttpRequestException
// with StatusCode set when the HTTP request status code isn't 2xx:
//
// GetByteArrayAsync
// GetStreamAsync
// GetStringAsync
using var stream = await httpClient.GetStreamAsync(
"https://localhost:5001/doesNotExists");
}
catch (HttpRequestException ex) when (ex is { StatusCode: HttpStatusCode.NotFound })
{
// Handle 404
Console.WriteLine($"Not found: {ex.Message}");
}
Mungkin ada skenario di mana Anda perlu melemparkan objek HttpRequestException dalam kode Anda. Konstruktor HttpRequestException() bersifat publik dan Anda dapat menggunakannya untuk melemparkan pengecualian dengan pesan kustom:
try
{
using var response = await httpClient.GetAsync(
"https://localhost:5001/doesNotExists");
// Throw for anything higher than 400.
if (response is { StatusCode: >= HttpStatusCode.BadRequest })
{
throw new HttpRequestException(
"Something went wrong", inner: null, response.StatusCode);
}
}
catch (HttpRequestException ex) when (ex is { StatusCode: HttpStatusCode.NotFound })
{
Console.WriteLine($"Not found: {ex.Message}");
}
Mengonfigurasi proksi HTTP
Proksi HTTP dapat dikonfigurasi dengan salah satu dari dua cara. Properti HttpClient.DefaultProxy memiliki nilai default. Atau, Anda dapat menentukan proksi pada HttpClientHandler.Proxy properti .
Gunakan proksi default global
Properti HttpClient.DefaultProxy
adalah properti statis yang menentukan proksi default yang digunakan semua instans HttpClient
, jika tidak ada proksi yang diatur secara eksplisit di objek HttpClientHandler yang diteruskan melalui konstruktornya.
Instans default yang dikembalikan oleh properti ini menginisialisasi sesuai dengan sekumpulan aturan yang berbeda tergantung pada platform Anda:
- Windows: Membaca konfigurasi proksi dari variabel lingkungan, atau jika variabel tidak ditentukan, baca dari pengaturan proksi pengguna.
- macOS : Membaca konfigurasi proksi dari variabel lingkungan, atau jika variabel tidak ditentukan, membacanya dari pengaturan proksi sistem.
- Linux: Membaca konfigurasi proksi dari variabel lingkungan, atau jika variabel tidak terdefinisi, menginisialisasi instans yang tidak dikonfigurasi untuk melewati semua alamat.
Inisialisasi properti DefaultProxy
pada platform berbasis Windows dan Unix menggunakan variabel lingkungan berikut:
-
HTTP_PROXY
: Server proksi yang digunakan pada permintaan HTTP. -
HTTPS_PROXY
: Server proksi yang digunakan pada permintaan HTTPS. -
ALL_PROXY
: Server proksi yang digunakan pada permintaan HTTP dan/atau HTTPS saat variabelHTTP_PROXY
dan/atauHTTPS_PROXY
tidak ditentukan. -
NO_PROXY
: Daftar nama host yang dipisahkan koma untuk dikecualikan dari proksi. Tanda bintang tidak didukung untuk simbol pengganti. Gunakan titik awal (.) saat Anda ingin mencocokkan subdomain. Contoh:NO_PROXY=.example.com
(dengan periode di depan) cocok denganwww.example.com
, tetapi tidak cocok denganexample.com
.NO_PROXY=example.com
(tanpa periode awal) tidak cocok denganwww.example.com
. Perilaku ini mungkin ditinjau kembali di masa depan untuk mencocokkan ekosistem lain dengan lebih baik.
Pada sistem di mana variabel lingkungan peka terhadap huruf kapital dan huruf kecil, nama variabel bisa semua huruf kecil atau semua huruf besar. Nama-nama huruf kecil diperiksa terlebih dahulu.
Server proksi dapat berupa nama host atau alamat IP, secara opsional diikuti oleh titik dua dan nomor port, atau dapat berupa URL http
, secara opsional termasuk nama pengguna dan kata sandi untuk autentikasi proksi. URL harus dimulai dengan http
, bukan https
, dan tidak dapat menyertakan teks apa pun setelah nama host, IP, atau port.
Mengonfigurasi proksi tiap klien
Properti HttpClientHandler.Proxy mengidentifikasi objek WebProxy untuk digunakan untuk memproses permintaan ke sumber daya internet. Untuk menentukan bahwa tidak ada proksi yang harus digunakan, atur properti Proxy
ke instans proksi yang dikembalikan oleh metode GlobalProxySelection.GetEmptyWebProxy().
File konfigurasi komputer atau aplikasi lokal mungkin menentukan bahwa proksi default digunakan. Jika properti Proxy
ditentukan, maka pengaturan proksi dari properti Proxy
mengambil alih komputer lokal atau file konfigurasi aplikasi dan handler menggunakan pengaturan proksi yang ditentukan. Jika tidak ada proksi yang ditentukan dalam file konfigurasi dan properti Proxy
tidak ditentukan, handler menggunakan pengaturan proksi yang diwariskan dari komputer lokal. Jika tidak ada pengaturan proksi, permintaan dikirim langsung ke server.
Kelas HttpClientHandler mengurai daftar bypass proksi dengan karakter wildcard yang diwarisi dari pengaturan lokal komputer. Misalnya, kelas HttpClientHandler
menguraikan daftar bypass dari browser "nt*"
sebagai ekspresi reguler "nt.*"
. Oleh karena itu, URL http://nt.com
melewati proksi dengan menggunakan kelas HttpClientHandler
.
Kelas HttpClientHandler
ini mendukung pengabaian proksi lokal. Kelas menganggap tujuan bersifat lokal jika salah satu kondisi berikut terpenuhi:
- Tujuan berisi nama datar (tanpa titik (.) di URL).
- Tujuan memiliki alamat loopback (Loopback atau IPv6Loopback) atau tujuan memiliki properti IPAddress yang ditetapkan pada komputer lokal.
- Akhiran domain tujuan cocok dengan akhiran domain komputer lokal, seperti yang didefinisikan dalam properti DomainName.
Untuk informasi selengkapnya tentang mengonfigurasi proksi, lihat API berikut:
- WebProxy.Address properti
- WebProxy.BypassProxyOnLocal properti
- WebProxy.BypassArrayList properti