Wysyłaj żądania HTTP za pomocą klasy HttpClient
W tym artykule dowiesz się, jak wysyłać żądania HTTP i obsługiwać odpowiedzi za pomocą HttpClient
klasy .
Ważne
Wszystkie przykładowe żądania HTTP są przeznaczone dla jednego z następujących adresów URL:
- https://jsonplaceholder.typicode.com: bezpłatny fałszywy interfejs API do testowania i tworzenia prototypów.
- https://www.example.com: Ta domena służy do użycia w ilustracyjnych przykładach w dokumentach.
Punkty końcowe HTTP często zwracają dane JavaScript Object Notation (JSON), ale nie zawsze. Dla wygody opcjonalny pakiet NuGet System.Net.Http.Json udostępnia kilka metod HttpClient
rozszerzeń i HttpContent
które wykonują automatyczną serializacji i deserializacji przy użyciu polecenia System.Text.Json
. Przykłady, które zwracają uwagę na miejsca, w których są dostępne te rozszerzenia.
Napiwek
Cały kod źródłowy z tego artykułu jest dostępny w repozytorium GitHub: .NET Docs .
Tworzenie elementu HttpClient
Większość poniższych przykładów ponownie używa tego samego HttpClient
wystąpienia i dlatego należy skonfigurować tylko raz. Aby utworzyć obiekt HttpClient
, użyj konstruktora HttpClient
klasy. Aby uzyskać więcej informacji, zobacz Wytyczne dotyczące korzystania z obiektu 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"),
};
Powyższy kod ma następujące działanie:
- Tworzy wystąpienie nowego
HttpClient
wystąpienia jako zmiennejstatic
. Zgodnie z wytycznymi zaleca się ponowne użycieHttpClient
wystąpień podczas cyklu życia aplikacji. - Ustawia wartość HttpClient.BaseAddress na
"https://jsonplaceholder.typicode.com"
.
To HttpClient
wystąpienie używa adresu podstawowego podczas wykonywania kolejnych żądań. Aby zastosować inną konfigurację, rozważ następujące kwestie:
- Ustawienie .HttpClient.DefaultRequestHeaders
- Stosowanie niezdefinicyjnego HttpClient.Timeoutpliku .
- Określanie wartości HttpClient.DefaultRequestVersion.
Napiwek
Alternatywnie można tworzyć HttpClient
wystąpienia przy użyciu podejścia opartego na wzorcu fabryki, które umożliwia skonfigurowanie dowolnej liczby klientów i użycie ich jako usług iniekcji zależności. Aby uzyskać więcej informacji, zobacz Http client factory with .NET (Fabryka klienta HTTP za pomocą platformy .NET).
Wysyłanie żądania HTTP
Aby wysłać żądanie HTTP, należy wywołać dowolny z następujących interfejsów API:
Metoda HTTP | interfejs 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 |
†A
USER SPECIFIED
żądanie wskazuje, żeSendAsync
metoda akceptuje wszystkie prawidłowe HttpMethod.
Ostrzeżenie
Wykonywanie żądań HTTP jest uznawane za pracę związaną z we/wy sieci. Chociaż istnieje metoda synchroniczna HttpClient.Send , zaleca się użycie asynchronicznych interfejsów API, chyba że nie masz dobrego powodu.
Uwaga
Podczas określania elementów docelowych dla urządzeń z systemem Android (takich jak programowanie na platformie .NET MAUI) należy dodać android:usesCleartextTraffic="true"
element <application></application>
w AndroidManifest.xml. Umożliwia to ruch w postaci zwykłego tekstu, taki jak żądania HTTP, który jest domyślnie wyłączony z powodu zasad zabezpieczeń systemu Android. Rozważmy następujące przykładowe ustawienia XML:
<?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>
Aby uzyskać więcej informacji, zobacz Włączanie ruchu sieciowego w postaci zwykłego tekstu dla domeny localhost.
Zawartość HTTP
Typ HttpContent jest używany do reprezentowania treści jednostki HTTP i odpowiednich nagłówków zawartości. W przypadku metod HTTP (lub metod żądań), które wymagają treści, POST
, PUT
i PATCH
, należy użyć HttpContent klasy , aby określić treść żądania. Większość przykładów pokazuje, jak przygotować podklasę StringContent z ładunkiem JSON, ale inne podklasy istnieją dla różnych typów zawartości (MIME).
- ByteArrayContent: udostępnia zawartość HTTP na podstawie tablicy bajtów.
- FormUrlEncodedContent: Udostępnia zawartość HTTP dla krotki nazwy/wartości zakodowane przy użyciu
"application/x-www-form-urlencoded"
typu MIME. - JsonContent: udostępnia zawartość HTTP opartą na formacie JSON.
- MultipartContent: udostępnia kolekcję obiektów HttpContent, które są serializowane przy użyciu
"multipart/*"
specyfikacji typu MIME. - MultipartFormDataContent: udostępnia kontener dla zawartości zakodowanej przy użyciu
"multipart/form-data"
typu MIME. - ReadOnlyMemoryContent: udostępnia zawartość HTTP na podstawie elementu ReadOnlyMemory<T>.
- StreamContent: udostępnia zawartość HTTP na podstawie strumienia.
- StringContent: udostępnia zawartość HTTP na podstawie ciągu.
Klasa HttpContent
jest również używana do reprezentowania treści HttpResponseMessageodpowiedzi obiektu , dostępnego we HttpResponseMessage.Content właściwości .
HTTP Get
Żądanie GET
nie powinno wysyłać treści i jest używane (jak wskazuje nazwa metody) do pobierania (lub pobierania) danych z zasobu. Aby utworzyć żądanie HTTP GET
, biorąc pod uwagę HttpClient
identyfikator URI i, użyj HttpClient.GetAsync metody :
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
// }
}
Powyższy kod ma następujące działanie:
GET
Wysyła żądanie do"https://jsonplaceholder.typicode.com/todos/3"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie.
- Zapisuje szczegóły żądania w konsoli programu .
- Odczytuje treść odpowiedzi jako ciąg.
- Zapisuje treść odpowiedzi JSON w konsoli.
Jest WriteRequestToConsole
to niestandardowa metoda rozszerzenia, która nie jest częścią struktury, ale jeśli interesuje Cię sposób implementacji, rozważ następujący kod języka C#:
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}");
}
}
Ta funkcja służy do zapisywania szczegółów żądania w konsoli w następującym formularzu:
<HTTP Request Method> <Request URI> <HTTP/Version>
Na przykład GET
żądanie do https://jsonplaceholder.typicode.com/todos/3
wyprowadzenia następującego komunikatu:
GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1
HTTP Get from JSON
Punkt https://jsonplaceholder.typicode.com/todos końcowy zwraca tablicę JSON obiektów "todo". Ich struktura JSON przypomina następujące elementy:
[
{
"userId": 1,
"id": 1,
"title": "example title",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "another example title",
"completed": true
},
]
Obiekt języka C# Todo
jest zdefiniowany w następujący sposób:
public record class Todo(
int? UserId = null,
int? Id = null,
string? Title = null,
bool? Completed = null);
Jest to record class
typ z opcjonalnymi Id
właściwościami , Title
, Completed
i UserId
. Aby uzyskać więcej informacji na record
temat typu, zobacz Wprowadzenie do typów rekordów w języku C#. Aby automatycznie deserializować GET
żądania do silnie typizowanego obiektu języka C#, użyj GetFromJsonAsync metody rozszerzenia będącej częścią pakietu NuGet System.Net.Http.Json .
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 }
}
Powyższy kod:
- Żądanie
GET
jest wykonywane do"https://jsonplaceholder.typicode.com/todos?userId=1&completed=false"
.- Ciąg zapytania reprezentuje kryteria filtrowania dla żądania.
- Odpowiedź jest automatycznie deserializowana w przypadku pomyślnego
List<Todo>
działania. - Szczegóły żądania są zapisywane w konsoli wraz z każdym
Todo
obiektem.
Wpis HTTP
Żądanie POST
wysyła dane do serwera na potrzeby przetwarzania. Nagłówek Content-Type
żądania oznacza typ MIME, który wysyła treść. Aby wysłać żądanie HTTP POST
, biorąc pod uwagę element HttpClient
i Uri, użyj HttpClient.PostAsync metody :
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
// }
}
Powyższy kod ma następujące działanie:
- StringContent Przygotowuje wystąpienie z treścią JSON żądania (typ MIME ).
"application/json"
POST
Wysyła żądanie do"https://jsonplaceholder.typicode.com/todos"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie i zapisze szczegóły żądania w konsoli.
- Zapisuje treść odpowiedzi jako ciąg w konsoli.
Wpis HTTP jako JSON
Aby automatycznie serializować POST
argumenty żądań i deserializować odpowiedzi na silnie typizowane obiekty języka C#, użyj PostAsJsonAsync metody rozszerzenia będącej częścią pakietu NuGet System.Net.Http.Json .
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 }
}
Powyższy kod ma następujące działanie:
- Serializuje
Todo
wystąpienie w formacie JSON i wysyłaPOST
żądanie do"https://jsonplaceholder.typicode.com/todos"
. - Gwarantuje, że odpowiedź zakończy się pomyślnie i zapisze szczegóły żądania w konsoli.
- Deserializuje treść odpowiedzi w wystąpieniu
Todo
i zapisuje elementTodo
w konsoli programu .
Umieszczanie http
Metoda PUT
żądania zastępuje istniejący zasób lub tworzy nowy za pomocą ładunku treści żądania. Aby utworzyć żądanie HTTP PUT
, biorąc pod uwagę HttpClient
identyfikator URI i, użyj HttpClient.PutAsync metody :
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
// }
}
Powyższy kod ma następujące działanie:
- StringContent Przygotowuje wystąpienie z treścią JSON żądania (typ MIME ).
"application/json"
PUT
Wysyła żądanie do"https://jsonplaceholder.typicode.com/todos/1"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie, a szczegóły żądania i treść odpowiedzi JSON zostaną zapisane w konsoli.
HTTP Put as JSON
Aby automatycznie serializować PUT
argumenty żądań i deserializować odpowiedzi na silnie typizowane obiekty języka C#, użyj metody rozszerzenia będącej PutAsJsonAsync częścią pakietu NuGet System.Net.Http.Json .
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 }
}
Powyższy kod ma następujące działanie:
- Serializuje
Todo
wystąpienie w formacie JSON i wysyłaPUT
żądanie do"https://jsonplaceholder.typicode.com/todos/5"
. - Gwarantuje, że odpowiedź zakończy się pomyślnie i zapisze szczegóły żądania w konsoli.
- Deserializuje treść odpowiedzi w wystąpieniu
Todo
i zapisuje elementTodo
w konsoli programu .
Poprawka HTTP
Żądanie PATCH
jest częściową aktualizacją istniejącego zasobu. Nie tworzy nowego zasobu i nie ma na celu zastąpienia istniejącego zasobu. Zamiast tego aktualizuje zasób tylko częściowo. Aby utworzyć żądanie HTTP PATCH
, biorąc pod uwagę HttpClient
identyfikator URI i, użyj HttpClient.PatchAsync metody :
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
// }
}
Powyższy kod ma następujące działanie:
- StringContent Przygotowuje wystąpienie z treścią JSON żądania (typ MIME ).
"application/json"
PATCH
Wysyła żądanie do"https://jsonplaceholder.typicode.com/todos/1"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie, a szczegóły żądania i treść odpowiedzi JSON zostaną zapisane w konsoli.
W pakiecie System.Net.Http.Json
NuGet nie istnieją PATCH
żadne metody rozszerzenia.
Usuwanie HTTP
Żądanie DELETE
usuwa istniejący zasób. Żądanie DELETE
jest idempotentne , ale nie bezpieczne, co oznacza, że wiele DELETE
żądań do tych samych zasobów daje ten sam wynik, ale żądanie wpływa na stan zasobu. Aby utworzyć żądanie HTTP DELETE
, biorąc pod uwagę HttpClient
identyfikator URI i, użyj HttpClient.DeleteAsync metody :
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
// {}
}
Powyższy kod ma następujące działanie:
DELETE
Wysyła żądanie do"https://jsonplaceholder.typicode.com/todos/1"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie i zapisze szczegóły żądania w konsoli.
Napiwek
Odpowiedź na DELETE
żądanie (podobnie jak PUT
żądanie) może lub nie może zawierać treści.
Nagłówek HTTP
Żądanie HEAD
jest podobne do GET
żądania. Zamiast zwracać zasób, zwraca on tylko nagłówki skojarzone z zasobem. Odpowiedź na HEAD
żądanie nie zwraca treści. Aby wysłać żądanie HTTP HEAD
, biorąc pod uwagę HttpClient
identyfikator URI i, użyj HttpClient.SendAsync metody z ustawionym HttpMethod na 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
}
Powyższy kod ma następujące działanie:
HEAD
Wysyła żądanie do"https://www.example.com/"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie i zapisze szczegóły żądania w konsoli.
- Iteruje wszystkie nagłówki odpowiedzi, zapisuj je w konsoli.
Opcje protokołu HTTP
Żądanie służy do identyfikowania OPTIONS
metod HTTP obsługiwanych przez serwer lub punkt końcowy. Aby wysłać żądanie HTTP OPTIONS
, biorąc pod uwagę HttpClient
identyfikator URI i, użyj HttpClient.SendAsync metody z ustawionym HttpMethod na 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
}
Powyższy kod ma następujące działanie:
OPTIONS
Wysyła żądanie HTTP do"https://www.example.com/"
.- Gwarantuje, że odpowiedź zakończy się pomyślnie i zapisze szczegóły żądania w konsoli.
- Iteruje wszystkie nagłówki zawartości odpowiedzi, zapisuj je w konsoli.
Śledzenie HTTP
Żądanie TRACE
może być przydatne do debugowania, ponieważ zapewnia pętlę na poziomie aplikacji z powrotem komunikatu żądania. Aby utworzyć żądanie HTTP TRACE
, utwórz obiekt HttpRequestMessage przy użyciu polecenia HttpMethod.Trace
:
using HttpRequestMessage request = new(
HttpMethod.Trace,
"{ValidRequestUri}");
Uwaga
Metoda HTTP nie jest obsługiwana TRACE
przez wszystkie serwery HTTP. Może ona ujawnić lukę w zabezpieczeniach, jeśli jest używana nierozsądnie. Aby uzyskać więcej informacji, zobacz Open Web Application Security Project (OWASP): Cross Site Tracing (Open Web Application Security Project: Cross Site Tracing).
Obsługa odpowiedzi HTTP
Za każdym razem, gdy obsługujesz odpowiedź HTTP, wchodzisz w interakcję z typem HttpResponseMessage . Podczas oceniania ważności odpowiedzi jest używanych kilka elementów członkowskich. Kod stanu HTTP jest dostępny za pośrednictwem HttpResponseMessage.StatusCode właściwości . Załóżmy, że wysłano żądanie dla danego wystąpienia klienta:
using HttpResponseMessage response = await httpClient.SendAsync(request);
Aby upewnić się, że element response
to OK
(kod stanu HTTP 200), możesz go ocenić, jak pokazano w poniższym przykładzie:
if (response is { StatusCode: HttpStatusCode.OK })
{
// Omitted for brevity...
}
Istnieją inne kody stanu HTTP, które reprezentują pomyślną odpowiedź, takie jak CREATED
(kod stanu HTTP 201), ACCEPTED
(kod stanu HTTP 202), NO CONTENT
(kod stanu HTTP 204) i RESET CONTENT
(kod stanu HTTP 205). Za pomocą HttpResponseMessage.IsSuccessStatusCode właściwości można również ocenić te kody, co gwarantuje, że kod stanu odpowiedzi mieści się w zakresie 200–299:
if (response.IsSuccessStatusCode)
{
// Omitted for brevity...
}
Jeśli musisz zgłosić strukturę HttpRequestException, możesz wywołać metodę HttpResponseMessage.EnsureSuccessStatusCode() :
response.EnsureSuccessStatusCode();
Ten kod zgłasza błąd, HttpRequestException
jeśli kod stanu odpowiedzi nie mieści się w zakresie od 200 do 299.
Prawidłowe odpowiedzi dotyczące zawartości HTTP
Prawidłową odpowiedzią można uzyskać dostęp do treści odpowiedzi przy użyciu Content właściwości . Treść jest dostępna jako HttpContent wystąpienie, którego można użyć do uzyskiwania dostępu do treści jako strumienia, tablicy bajtów lub ciągu:
await using Stream responseStream =
await response.Content.ReadAsStreamAsync();
W poprzednim kodzie responseStream
można go użyć do odczytania treści odpowiedzi.
byte[] responseByteArray = await response.Content.ReadAsByteArrayAsync();
W poprzednim kodzie responseByteArray
można go użyć do odczytania treści odpowiedzi.
string responseString = await response.Content.ReadAsStringAsync();
W poprzednim kodzie responseString
można go użyć do odczytania treści odpowiedzi.
Na koniec, gdy wiesz, że punkt końcowy HTTP zwraca kod JSON, można deserializować treść odpowiedzi do dowolnego prawidłowego obiektu języka C# przy użyciu pakietu NuGet System.Net.Http.Json :
T? result = await response.Content.ReadFromJsonAsync<T>();
W poprzednim kodzie result
jest treść odpowiedzi deserializowana jako typ T
.
Obsługa błędów HTTP
Gdy żądanie HTTP zakończy się niepowodzeniem, HttpRequestException zostanie zgłoszony. Przechwycenie tego wyjątku może nie być wystarczające, ponieważ istnieją inne potencjalne wyjątki, które mogą być zgłaszane, że warto rozważyć obsługę. Na przykład kod wywołujący mógł używać tokenu anulowania, który został anulowany przed ukończeniem żądania. W tym scenariuszu przechwycisz element 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}");
}
Podobnie podczas tworzenia żądania HTTP, jeśli serwer nie odpowiada przed HttpClient.Timeout przekroczeniem tego samego wyjątku, zostanie zgłoszony ten sam wyjątek. Jednak w tym scenariuszu można odróżnić limit czasu, oceniając Exception.InnerException wartość podczas przechwytywania elementu 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}");
}
W poprzednim kodzie, gdy wyjątek wewnętrzny jest przekroczeniem TimeoutException limitu czasu, a żądanie nie zostało anulowane przez token anulowania.
Aby ocenić kod stanu HTTP podczas przechwytywania HttpRequestExceptionelementu , możesz ocenić HttpRequestException.StatusCode właściwość :
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}");
}
W poprzednim kodzie wywoływana EnsureSuccessStatusCode() jest metoda , aby zgłosić wyjątek, jeśli odpowiedź nie powiedzie się. Następnie HttpRequestException.StatusCode właściwość jest oceniana w celu określenia, czy odpowiedź była ( 404
kod stanu HTTP 404). Istnieje kilka metod HttpClient
pomocnika, które niejawnie wywołuje EnsureSuccessStatusCode
w Twoim imieniu, rozważ następujące interfejsy API:
Napiwek
Wszystkie HttpClient
metody używane do wykonywania żądań HTTP, które nie zwracają HttpResponseMessage
niejawnie wywołania EnsureSuccessStatusCode
w Twoim imieniu.
Podczas wywoływania tych metod można obsłużyć HttpRequestException
i ocenić HttpRequestException.StatusCode właściwość , aby określić kod stanu HTTP odpowiedzi:
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}");
}
Mogą istnieć scenariusze, w których trzeba zgłosić element HttpRequestException w kodzie. Konstruktor HttpRequestException() jest publiczny i można go użyć do zgłaszania wyjątku z niestandardowym komunikatem:
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}");
}
Serwer proxy HTTP
Serwer proxy HTTP można skonfigurować na jeden z dwóch sposobów. Wartość domyślna jest określona we HttpClient.DefaultProxy właściwości . Alternatywnie można określić serwer proxy we HttpClientHandler.Proxy właściwości .
Globalny domyślny serwer proxy
Jest HttpClient.DefaultProxy
to właściwość statyczna, która określa domyślny serwer proxy używany przez wszystkie HttpClient
wystąpienia, jeśli żaden serwer proxy nie jest jawnie ustawiony w HttpClientHandler przekazanym konstruktorze.
Wystąpienie domyślne zwracane przez tę właściwość inicjuje inny zestaw reguł w zależności od platformy:
- W przypadku systemu Windows: odczytuje konfigurację serwera proxy ze zmiennych środowiskowych lub, jeśli nie są one zdefiniowane, z ustawień serwera proxy użytkownika.
- W przypadku systemu macOS: odczytuje konfigurację serwera proxy ze zmiennych środowiskowych lub, jeśli nie są one zdefiniowane, z ustawień serwera proxy systemu.
- W przypadku systemu Linux: odczytuje konfigurację serwera proxy ze zmiennych środowiskowych lub, jeśli te nie są zdefiniowane, ta właściwość inicjuje nieskonfigurowane wystąpienie, które pomija wszystkie adresy.
Zmienne środowiskowe używane do DefaultProxy
inicjowania na platformach opartych na systemach Windows i Unix to:
HTTP_PROXY
: serwer proxy używany na żądaniach HTTP.HTTPS_PROXY
: serwer proxy używany w żądaniach HTTPS.ALL_PROXY
: serwer proxy używany na żądaniach HTTP i/lub HTTPS w przypadku, gdyHTTP_PROXY
i/lubHTTPS_PROXY
nie są zdefiniowane.NO_PROXY
: rozdzielona przecinkami lista nazw hostów, które powinny być wykluczone z serwera proxy. Gwiazdki nie są obsługiwane w przypadku symboli wieloznacznych; użyj wiodącej kropki w przypadku dopasowania poddomeny. Przykłady:NO_PROXY=.example.com
(z kropką wiodącą) będzie zgodnawww.example.com
z wartością , ale nie będzie zgodnaexample.com
z parametrem .NO_PROXY=example.com
(bez wiodącej kropki) nie będzie pasujewww.example.com
do . To zachowanie może zostać ponownie zwrócone w przyszłości, aby lepiej dopasować inne ekosystemy.
W systemach, w których zmienne środowiskowe są uwzględniane wielkości liter, nazwy zmiennych mogą być małymi literami lub wielką literą. Najpierw sprawdzane są małe litery.
Serwer proxy może być nazwą hosta lub adresem IP, opcjonalnie, po którym następuje dwukropek i numer portu, lub może to być http
adres URL, opcjonalnie, w tym nazwa użytkownika i hasło na potrzeby uwierzytelniania serwera proxy. Adres URL musi zaczynać się od http
, a nie https
, i nie może zawierać żadnego tekstu po nazwie hosta, adresie IP lub porcie.
Serwer proxy na klienta
Właściwość HttpClientHandler.Proxy identyfikuje WebProxy obiekt używany do przetwarzania żądań do zasobów internetowych. Aby określić, że nie należy używać serwera proxy, ustaw Proxy
właściwość na wystąpienie serwera proxy zwrócone przez metodę GlobalProxySelection.GetEmptyWebProxy() .
Plik konfiguracji komputera lokalnego lub aplikacji może określać, że jest używany domyślny serwer proxy. Jeśli właściwość serwera proxy jest określona, ustawienia serwera proxy z właściwości serwera proxy zastępują plik konfiguracji komputera lokalnego lub aplikacji, a program obsługi używa określonych ustawień serwera proxy. Jeśli w pliku konfiguracji nie określono żadnego serwera proxy, a właściwość serwera proxy nie jest określona, program obsługi używa ustawień serwera proxy dziedziczonych z komputera lokalnego. Jeśli nie ma żadnych ustawień serwera proxy, żądanie jest wysyłane bezpośrednio do serwera.
Klasa HttpClientHandler analizuje listę obejścia serwera proxy z symbolami wieloznacznymi dziedziczone z ustawień komputera lokalnego. Na przykład HttpClientHandler
klasa analizuje listę pomijania "nt*"
z przeglądarek jako wyrażenie regularne ."nt.*"
Dlatego adres URL http://nt.com
polecenia pomija serwer proxy przy użyciu HttpClientHandler
klasy .
Klasa HttpClientHandler
obsługuje obejście lokalnego serwera proxy. Klasa uważa miejsce docelowe za lokalizację lokalną, jeśli zostaną spełnione jakiekolwiek z następujących warunków:
- Miejsce docelowe zawiera płaską nazwę (bez kropek w adresie URL).
- Miejsce docelowe zawiera adres sprzężenia zwrotnego (Loopback lub ) lub IPv6Loopbackmiejsce docelowe zawiera przypisaną IPAddress do komputera lokalnego.
- Sufiks domeny miejsca docelowego jest zgodny z sufiksem domeny komputera lokalnego (DomainName).
Aby uzyskać więcej informacji na temat konfigurowania serwera proxy, zobacz: