Membuat permintaan HTTP dengan kelas HttpClient
Dalam artikel ini, Anda akan mempelajari cara membuat permintaan HTTP dan menangani respons dengan HttpClient
kelas .
Penting
Semua contoh permintaan HTTP menargetkan salah satu URL berikut:
- https://jsonplaceholder.typicode.com: API palsu gratis untuk pengujian dan prototipe.
- https://www.example.com: Domain ini 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 HttpClient
dan HttpContent
yang melakukan serialisasi dan deserialisasi otomatis menggunakan System.Text.Json
. Contoh yang mengikuti panggilan perhatian ke tempat-tempat di mana ekstensi ini tersedia.
Tip
Semua kode sumber dari artikel ini tersedia di repositori GitHub: .NET Docs .
Buat HttpClient
Sebagian besar contoh berikut menggunakan kembali instans yang sama HttpClient
, dan oleh karena itu hanya perlu dikonfigurasi sekali. Untuk membuat HttpClient
, gunakan HttpClient
konstruktor kelas. 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 sebelumnya:
- Membuat instans baru
HttpClient
sebagaistatic
variabel. Sesuai pedoman, disarankan untuk menggunakanHttpClient
kembali instans selama siklus hidup aplikasi. - Mengatur ke HttpClient.BaseAddress
"https://jsonplaceholder.typicode.com"
.
Instans ini HttpClient
menggunakan alamat dasar saat membuat permintaan berikutnya. Untuk menerapkan konfigurasi lain, pertimbangkan:
- Mengatur HttpClient.DefaultRequestHeaders.
- Menerapkan nondefault HttpClient.Timeout.
- HttpClient.DefaultRequestVersionMenentukan .
Tip
Atau, Anda dapat membuat HttpClient
instans menggunakan pendekatan pola pabrik yang memungkinkan Anda mengonfigurasi sejumlah klien dan menggunakannya sebagai layanan injeksi dependensi. Untuk informasi selengkapnya, lihat pabrik klien HTTP dengan .NET.
Membuat permintaan HTTP
Untuk membuat permintaan HTTP, Anda memanggil salah satu 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 †A
USER SPECIFIED
menunjukkan bahwa metode menerima apa pun yangSendAsync
validHttpMethod.
Peringatan
Membuat permintaan HTTP dianggap sebagai pekerjaan terikat I/O jaringan. Meskipun ada metode sinkron HttpClient.Send , disarankan untuk menggunakan API asinkron sebagai gantinya, kecuali Anda memiliki alasan yang baik untuk tidak melakukannya.
Catatan
Saat menargetkan perangkat Android (seperti dengan pengembangan .NET MAUI), Anda harus menambahkannya android:usesCleartextTraffic="true"
<application></application>
di AndroidManifest.xml. 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 jaringan teks-jelas untuk domain localhost.
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
, dan PATCH
, Anda menggunakan HttpContent kelas 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 tuple nama/nilai yang dikodekan menggunakan
"application/x-www-form-urlencoded"
jenis MIME. - JsonContent: Menyediakan konten HTTP berdasarkan JSON.
- MultipartContent: Menyediakan kumpulan objek HttpContent yang diserialisasikan menggunakan
"multipart/*"
spesifikasi jenis MIME. - MultipartFormDataContent: Menyediakan kontainer untuk konten yang dikodekan menggunakan
"multipart/form-data"
jenis MIME. - ReadOnlyMemoryContent: Menyediakan konten HTTP berdasarkan ReadOnlyMemory<T>.
- StreamContent: Menyediakan konten HTTP berdasarkan aliran.
- StringContent: Menyediakan konten HTTP berdasarkan string.
Kelas HttpContent
ini juga digunakan untuk mewakili isi respons , HttpResponseMessageyang dapat diakses pada HttpResponseMessage.Content properti .
HTTP Get
Permintaan GET
tidak boleh mengirim isi dan digunakan (seperti yang ditunjukkan oleh nama metode) untuk mengambil (atau mendapatkan) data dari sumber daya. Untuk membuat permintaan HTTP GET
, yang diberikan HttpClient
dan URI, gunakan HttpClient.GetAsync metode :
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 sebelumnya:
- Membuat
GET
permintaan ke"https://jsonplaceholder.typicode.com/todos/3"
. - Memastikan bahwa respons berhasil.
- Menulis detail permintaan ke konsol.
- Membaca isi respons sebagai string.
- Menulis isi respons JSON ke konsol.
WriteRequestToConsole
adalah metode ekstensi kustom yang bukan bagian dari kerangka kerja, tetapi jika Anda ingin tahu tentang bagaimana penerapannya, 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, GET
permintaan untuk https://jsonplaceholder.typicode.com/todos/3
menghasilkan pesan berikut:
GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1
HTTP Get dari JSON
Titik https://jsonplaceholder.typicode.com/todos akhir mengembalikan array JSON dari objek "todo". Struktur JSON mereka menyerupan 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 record class
jenis, dengan properti opsional Id
, , Title
Completed
, dan UserId
. Untuk informasi selengkapnya tentang jenisnya record
, lihat Pengenalan jenis rekaman di C#. Untuk secara otomatis mendeserialisasi GET
permintaan ke objek C# yang sangat ditik, gunakan GetFromJsonAsync metode ekstensi 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 }
}
Dalam kode sebelumnya:
- Permintaan
GET
dibuat untuk"https://jsonplaceholder.typicode.com/todos?userId=1&completed=false"
.- String kueri mewakili kriteria pemfilteran untuk permintaan.
- Respons secara otomatis dideserialisasi menjadi
List<Todo>
ketika berhasil. - Detail permintaan ditulis ke konsol, bersama dengan setiap
Todo
objek.
Posting HTTP
Permintaan POST
mengirim data ke server untuk diproses. Header Content-Type
permintaan menandakan jenis MIME apa yang dikirim oleh isi. Untuk membuat permintaan HTTP POST
, diberikan HttpClient
dan Uri, gunakan HttpClient.PostAsync metode :
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 sebelumnya:
- Menyiapkan instans StringContent dengan isi JSON permintaan (jenis
"application/json"
MIME ). - Membuat
POST
permintaan ke"https://jsonplaceholder.typicode.com/todos"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan ke konsol.
- Menulis isi respons sebagai string ke konsol.
Http Post sebagai JSON
Untuk secara otomatis menserialisasikan POST
argumen permintaan dan mendeserialisasi respons ke dalam objek C# yang sangat ditik, 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 sebelumnya:
- Menserialisasikan instans
Todo
sebagai JSON, dan membuatPOST
permintaan ke"https://jsonplaceholder.typicode.com/todos"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan ke konsol.
- Mendeserialisasi isi respons ke dalam
Todo
instans, dan menulis keTodo
konsol.
HTTP Put
Metode PUT
permintaan menggantikan sumber daya yang ada atau membuat sumber daya baru menggunakan payload isi permintaan. Untuk membuat permintaan HTTP PUT
, yang diberikan HttpClient
dan URI, gunakan HttpClient.PutAsync metode :
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 sebelumnya:
- Menyiapkan instans StringContent dengan isi JSON permintaan (jenis
"application/json"
MIME ). - Membuat
PUT
permintaan ke"https://jsonplaceholder.typicode.com/todos/1"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan dan isi respons JSON ke konsol.
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 sebelumnya:
- Menserialisasikan instans
Todo
sebagai JSON, dan membuatPUT
permintaan ke"https://jsonplaceholder.typicode.com/todos/5"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan ke konsol.
- Mendeserialisasi isi respons ke dalam
Todo
instans, dan menulis keTodo
konsol.
HTTP Patch
Permintaan PATCH
adalah pembaruan parsial ke sumber daya yang ada. Ini tidak membuat sumber daya baru, dan tidak dimaksudkan untuk menggantikan sumber daya yang ada. Sebaliknya, ini memperbarui sumber daya hanya sebagian. Untuk membuat permintaan HTTP PATCH
, yang diberikan HttpClient
dan URI, gunakan HttpClient.PatchAsync metode :
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 sebelumnya:
- Menyiapkan instans StringContent dengan isi JSON permintaan (jenis
"application/json"
MIME ). - Membuat
PATCH
permintaan ke"https://jsonplaceholder.typicode.com/todos/1"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan dan isi respons JSON ke konsol.
Tidak ada metode ekstensi untuk PATCH
permintaan dalam System.Net.Http.Json
paket NuGet.
Penghapusan HTTP
Permintaan DELETE
menghapus sumber daya yang ada. Permintaan DELETE
idempoten tetapi tidak aman, yang berarti beberapa DELETE
permintaan ke sumber daya yang sama menghasilkan hasil yang sama, tetapi permintaan memengaruhi status sumber daya. Untuk membuat permintaan HTTP DELETE
, yang diberikan HttpClient
dan URI, gunakan HttpClient.DeleteAsync metode :
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 sebelumnya:
- Membuat
DELETE
permintaan ke"https://jsonplaceholder.typicode.com/todos/1"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan ke konsol.
Tip
Respons terhadap DELETE
permintaan (sama seperti PUT
permintaan) mungkin atau mungkin tidak menyertakan isi.
Kepala HTTP
Permintaan HEAD
ini mirip GET
dengan permintaan. Alih-alih mengembalikan sumber daya, sumber daya hanya mengembalikan header yang terkait dengan sumber daya. Respons terhadap HEAD
permintaan tidak mengembalikan isi. Untuk membuat permintaan HTTP HEAD
, yang diberikan HttpClient
dan URI, gunakan HttpClient.SendAsync metode dengan HttpMethod set 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 sebelumnya:
- Membuat
HEAD
permintaan ke"https://www.example.com/"
. - Memastikan bahwa respons berhasil, dan menulis detail permintaan ke konsol.
- Iterasi atas semua header respons, menulis masing-masing ke konsol.
Opsi HTTP
Permintaan OPTIONS
digunakan untuk mengidentifikasi metode HTTP mana yang didukung server atau titik akhir. Untuk membuat permintaan HTTP OPTIONS
, yang diberikan HttpClient
dan URI, gunakan HttpClient.SendAsync metode dengan HttpMethod set 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 sebelumnya:
OPTIONS
Mengirim permintaan HTTP ke"https://www.example.com/"
.- Memastikan bahwa respons berhasil, dan menulis detail permintaan ke konsol.
- Melakukan iterasi atas semua header konten respons, menulis masing-masing ke konsol.
Pelacakan HTTP
Permintaan TRACE
dapat berguna untuk penelusuran kesalahan karena menyediakan loop-back tingkat aplikasi dari pesan permintaan. Untuk membuat permintaan HTTP TRACE
, buat HttpRequestMessage menggunakan HttpMethod.Trace
:
using HttpRequestMessage request = new(
HttpMethod.Trace,
"{ValidRequestUri}");
Perhatian
Metode TRACE
HTTP tidak didukung oleh semua server HTTP. Ini dapat mengekspos kerentanan keamanan jika digunakan dengan tidak bijaksakan. Untuk informasi selengkapnya, lihat Membuka Proyek Keamanan Aplikasi Web (OWASP): Pelacakan Lintas Situs.
Menangani respons HTTP
Setiap kali Anda menangani respons HTTP, Anda berinteraksi dengan jenis tersebut HttpResponseMessage . Beberapa anggota digunakan saat mengevaluasi validitas respons. Kode status HTTP tersedia melalui HttpResponseMessage.StatusCode properti . Bayangkan Anda telah mengirim permintaan yang diberikan instans klien:
using HttpResponseMessage response = await httpClient.SendAsync(request);
Untuk memastikan bahwa adalah OK
(kode status HTTP 200), Anda dapat mengevaluasinya seperti yang response
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 membuat kerangka kerja melemparkan HttpRequestException, Anda dapat memanggil HttpResponseMessage.EnsureSuccessStatusCode() metode :
response.EnsureSuccessStatusCode();
Kode ini menampilkan HttpRequestException
jika kode status respons tidak berada dalam rentang 200-299.
Respons konten http yang valid
Dengan respons yang valid, Anda dapat mengakses isi respons menggunakan Content properti . Isi tersedia sebagai HttpContent instans, yang dapat Anda gunakan untuk mengakses isi sebagai aliran, array byte, atau string:
await using Stream responseStream =
await response.Content.ReadAsStreamAsync();
Dalam kode sebelumnya, responseStream
dapat digunakan untuk membaca isi respons.
byte[] responseByteArray = await response.Content.ReadAsByteArrayAsync();
Dalam kode sebelumnya, responseByteArray
dapat digunakan untuk membaca isi respons.
string responseString = await response.Content.ReadAsStringAsync();
Dalam kode sebelumnya, responseString
dapat digunakan untuk membaca isi respons.
Terakhir, 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 sebelumnya, result
adalah isi respons yang dideserialisasi sebagai jenis T
.
Penanganan kesalahan HTTP
Ketika permintaan HTTP gagal, permintaan akan HttpRequestException dilemparkan. Menangkap pengecualian itu saja mungkin tidak cukup, karena ada pengecualian potensial lainnya yang mungkin ingin Anda pertimbangkan penanganannya. Misalnya, kode panggilan mungkin telah menggunakan token pembatalan yang dibatalkan sebelum permintaan selesai. Dalam skenario ini, Anda akan menangkap 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, saat membuat permintaan HTTP, jika server tidak merespons sebelum HttpClient.Timeout terlampaui pengecualian yang sama dilemparkan. Namun, dalam skenario ini, Anda dapat membedakan bahwa batas waktu terjadi dengan mengevaluasi Exception.InnerException saat menangkap 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 sebelumnya, ketika pengecualian dalam adalah TimeoutException batas waktu terjadi, dan permintaan tidak dibatalkan oleh token pembatalan.
Untuk mengevaluasi kode status HTTP saat menangkap HttpRequestException, Anda dapat mengevaluasi HttpRequestException.StatusCode properti :
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 sebelumnya, EnsureSuccessStatusCode() metode ini 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 atas HttpClient
panggilan EnsureSuccessStatusCode
implisit atas nama Anda, pertimbangkan API berikut:
Tip
Semua HttpClient
metode yang digunakan untuk membuat permintaan HTTP yang tidak mengembalikan HttpResponseMessage
panggilan EnsureSuccessStatusCode
implisit atas nama Anda.
Saat memanggil metode ini, Anda dapat menangani HttpRequestException
dan mengevaluasi HttpRequestException.StatusCode properti 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 dalam HttpRequestException kode Anda. HttpRequestException() Konstruktor 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}");
}
Proksi HTTP
Proksi HTTP dapat dikonfigurasi dengan salah satu dari dua cara. Default ditentukan pada HttpClient.DefaultProxy properti . Atau, Anda dapat menentukan proksi pada HttpClientHandler.Proxy properti .
Proksi default global
HttpClient.DefaultProxy
adalah properti statis yang menentukan proksi default yang digunakan semua HttpClient
instans jika tidak ada proksi yang diatur secara eksplisit dalam yang diteruskan HttpClientHandler melalui konstruktornya.
Instans default yang dikembalikan oleh properti ini menginisialisasi mengikuti serangkaian aturan yang berbeda tergantung pada platform Anda:
- Untuk Windows: Membaca konfigurasi proksi dari variabel lingkungan atau, jika tidak ditentukan, dari pengaturan proksi pengguna.
- Untuk macOS: Membaca konfigurasi proksi dari variabel lingkungan atau, jika tidak ditentukan, dari pengaturan proksi sistem.
- Untuk Linux: Membaca konfigurasi proksi dari variabel lingkungan atau, jika tidak ditentukan, properti ini menginisialisasi instans yang tidak dikonfigurasi yang melewati semua alamat.
Variabel lingkungan yang digunakan untuk DefaultProxy
inisialisasi pada platform berbasis Windows dan Unix adalah:
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 jikaHTTP_PROXY
dan/atauHTTPS_PROXY
tidak ditentukan.NO_PROXY
: daftar nama host yang dipisahkan koma yang harus dikecualikan dari proksi. Tanda bintang tidak didukung untuk kartubebas; gunakan titik di depan jika Anda ingin mencocokkan subdomain. Contoh:NO_PROXY=.example.com
(dengan titik terdepan) akan cocokwww.example.com
, tetapi tidak akan cocokexample.com
dengan .NO_PROXY=example.com
(tanpa titik terdepan) tidak akan cocokwww.example.com
. Perilaku ini mungkin ditinjau kembali di masa depan untuk mencocokkan ekosistem lain dengan lebih baik.
Pada sistem di mana variabel lingkungan peka huruf besar/kecil, nama variabel bisa semua huruf kecil atau huruf besar. Nama-nama huruf kecil diperiksa terlebih dahulu.
Server proksi mungkin berupa nama host atau alamat IP, secara opsional diikuti oleh titik dua dan nomor port, atau mungkin 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.
Proksi per klien
Properti HttpClientHandler.Proxy mengidentifikasi objek yang WebProxy akan digunakan untuk memproses permintaan ke sumber daya Internet. Untuk menentukan bahwa tidak ada proksi yang harus digunakan, atur Proxy
properti ke instans proksi yang dikembalikan oleh GlobalProxySelection.GetEmptyWebProxy() metode .
File konfigurasi komputer atau aplikasi lokal dapat menentukan bahwa proksi default digunakan. Jika properti Proksi ditentukan, maka pengaturan proksi dari properti Proksi 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 Proksi tidak ditentukan, handler menggunakan pengaturan proksi yang diwarisi dari komputer lokal. Jika tidak ada pengaturan proksi, permintaan dikirim langsung ke server.
Kelas HttpClientHandler mengurai daftar bypass proksi dengan karakter kartubebas yang diwarisi dari pengaturan komputer lokal. Misalnya, HttpClientHandler
kelas mengurai daftar bypass dari "nt*"
browser sebagai ekspresi reguler ."nt.*"
Jadi URL http://nt.com
akan melewati proksi menggunakan HttpClientHandler
kelas .
Kelas HttpClientHandler
ini mendukung bypass proksi lokal. Kelas menganggap tujuan bersifat lokal jika salah satu kondisi berikut terpenuhi:
- Tujuan berisi nama datar (tidak ada titik di URL).
- Tujuan berisi alamat loopback (Loopback atau IPv6Loopback) atau tujuan berisi yang IPAddress ditetapkan ke komputer lokal.
- Akhiran domain tujuan cocok dengan akhiran domain komputer lokal (DomainName).
Untuk informasi selengkapnya tentang mengonfigurasi proksi, lihat: