Provádění požadavků HTTP pomocí třídy HttpClient

V tomto článku se dozvíte, jak provádět požadavky HTTP a zpracovávat odpovědi pomocí HttpClient třídy.

Důležité

Všechny ukázkové požadavky HTTP cílí na jednu z následujících adres URL:

Koncové body HTTP obvykle vrací data JSON (JavaScript Object Notation), ale ne vždy. Pro usnadnění práce poskytuje volitelný balíček NuGet System.Net.Http.Json několik rozšiřujících metod a HttpClient HttpContent provádí automatické serializace a deserializace pomocí System.Text.Json. Příklady, které upozorní na místa, kde jsou tato rozšíření k dispozici.

Tip

Veškerý zdrojový kód z tohoto článku je k dispozici v úložišti GitHub: .NET Docs .

Vytvoření HttpClient

Většina následujících příkladů znovu používá stejnou HttpClient instanci, a proto je potřeba ji nakonfigurovat pouze jednou. Chcete-li vytvořit , HttpClientpoužijte HttpClient konstruktor třídy. Další informace naleznete v tématu Pokyny pro použití HttpClient.

// HttpClient lifecycle management best practices:
// https://video2.skills-academy.com/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use
private static HttpClient sharedClient = new()
{
    BaseAddress = new Uri("https://jsonplaceholder.typicode.com"),
};

Předchozí kód:

  • Vytvoří instanci nové HttpClient instance jako proměnnou static . Podle pokynů se doporučuje opakovaně používat HttpClient instance během životního cyklu aplikace.
  • HttpClient.BaseAddress Nastaví na "https://jsonplaceholder.typicode.com".

Tato HttpClient instance používá základní adresu při provádění následných požadavků. Pokud chcete použít jinou konfiguraci, zvažte následující:

Tip

Alternativně můžete vytvářet HttpClient instance pomocí přístupu vzoru továrny, který umožňuje nakonfigurovat libovolný počet klientů a využívat je jako služby injektáže závislostí. Další informace najdete v tématu Klientská továrna HTTP s .NET.

Vytvoření požadavku HTTP

Pokud chcete vytvořit požadavek HTTP, zavoláte některá z následujících rozhraní API:

Metoda HTTP: rozhraní 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 požadavek indikuje, že SendAsync metoda přijímá všechny platné HttpMethod.

Upozorňující

Vytváření požadavků HTTP se považuje za práci vázané na vstupně-výstupní operace sítě. I když existuje synchronní HttpClient.Send metoda, doporučuje se místo toho použít asynchronní rozhraní API, pokud nemáte dobrý důvod, proč ne.

Poznámka:

Při cílení na zařízení s Androidem (jako je vývoj pro .NET MAUI) je nutné přidat android:usesCleartextTraffic="true" do <application></application> AndroidManifest.xml. To umožňuje přenosy s vymazáním textu, jako jsou požadavky HTTP, které jsou jinak zakázány ve výchozím nastavení kvůli zásadám zabezpečení Androidu. Představte si následující příklad nastavení 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>

Další informace najdete v tématu Povolení síťového provozu s vymazáním textu pro doménu localhost.

Obsah HTTP

Typ HttpContent se používá k reprezentaci těla entity HTTP a odpovídající hlavičky obsahu. Pro metody HTTP (nebo metody požadavku), které vyžadují tělo , POSTPUTa PATCH, použijete HttpContent třídu k určení textu požadavku. Většina příkladů ukazuje, jak připravit podtřídu StringContent datovou částí JSON, ale pro různé typy obsahu (MIME) existují i jiné podtřídy.

Třída HttpContent se také používá k reprezentaci textu HttpResponseMessageodpovědi , přístupného ve HttpResponseMessage.Content vlastnosti.

Metoda HTTP Get

GET Požadavek by neměl posílat text a používá se (jak název metody označuje) k načtení (nebo získání) dat z prostředku. Pokud chcete vytvořit požadavek HTTP GET s použitím identifikátoru HttpClient URI, použijte metodu 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
    //   }
}

Předchozí kód:

  • GET Odešle požadavek na "https://jsonplaceholder.typicode.com/todos/3".
  • Zajišťuje, že odpověď bude úspěšná.
  • Zapíše podrobnosti žádosti do konzoly.
  • Přečte text odpovědi jako řetězec.
  • Zapíše text odpovědi JSON do konzoly.

Jedná WriteRequestToConsole se o vlastní metodu rozšíření, která není součástí architektury, ale pokud vás zajímá, jak je implementovaná, zvažte následující kód jazyka 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}");        
    }
}

Tato funkce slouží k zápisu podrobností žádosti do konzoly v následujícím formátu:

<HTTP Request Method> <Request URI> <HTTP/Version>

GET Například požadavek na https://jsonplaceholder.typicode.com/todos/3 výstup následující zprávy:

GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1

Http Get z JSON

Koncový https://jsonplaceholder.typicode.com/todos bod vrátí pole JSON objektů "todo". Jejich struktura JSON vypadá takto:

[
  {
    "userId": 1,
    "id": 1,
    "title": "example title",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "another example title",
    "completed": true
  },
]

Objekt C# Todo je definován takto:

public record class Todo(
    int? UserId = null,
    int? Id = null,
    string? Title = null,
    bool? Completed = null);

Jedná se o typ s volitelnými record class Idvlastnostmi , Title, Completeda UserId vlastnostmi. Další informace o record typu najdete v tématu Úvod k typům záznamů v jazyce C#. Pokud chcete automaticky deserializovat GET požadavky do objektu jazyka C# silného typu, použijte metodu GetFromJsonAsync rozšíření, která je součástí balíčku 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 }
}

V předchozím kódu:

  • Žádost je podána GET do "https://jsonplaceholder.typicode.com/todos?userId=1&completed=false".
    • Řetězec dotazu představuje kritéria filtrování požadavku.
  • Odpověď se po úspěšném dokončení automaticky deserializuje na List<Todo> .
  • Podrobnosti žádosti se zapisují do konzoly spolu s každým Todo objektem.

Příspěvek HTTP

Požadavek POST odešle data na server ke zpracování. Hlavička Content-Type požadavku označuje, jaký typ MIME text odesílá. Pokud chcete vytvořit požadavek HTTP POST s ohledem na HttpClient metodu a metodu HttpClient.PostAsync Uri, použijte:

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
    //   }
}

Předchozí kód:

  • StringContent Připraví instanci s textem JSON požadavku (typ "application/json"MIME).
  • POST Odešle požadavek na "https://jsonplaceholder.typicode.com/todos".
  • Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
  • Zapíše text odpovědi jako řetězec do konzoly.

Publikování HTTP ve formátu JSON

Pokud chcete automaticky serializovat POST argumenty požadavku a deserializovat odpovědi na objekty C# silného typu, použijte PostAsJsonAsync rozšiřující metodu, která je součástí balíčku 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 }
}

Předchozí kód:

  • Serializuje Todo instanci jako JSON a odešle POST požadavek na "https://jsonplaceholder.typicode.com/todos".
  • Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
  • Deserializuje tělo odpovědi do Todo instance a zapíše do Todo konzoly.

HTTP Put

Metoda PUT požadavku buď nahradí existující prostředek, nebo vytvoří nový pomocí datové části textu požadavku. Pokud chcete vytvořit požadavek HTTP PUT s použitím identifikátoru HttpClient URI, použijte metodu 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
    //   }
}

Předchozí kód:

  • StringContent Připraví instanci s textem JSON požadavku (typ "application/json"MIME).
  • PUT Odešle požadavek na "https://jsonplaceholder.typicode.com/todos/1".
  • Zajišťuje, že odpověď proběhne úspěšně, a zapíše do konzoly podrobnosti požadavku a text odpovědi JSON.

HTTP Put as JSON

Pokud chcete automaticky serializovat PUT argumenty požadavku a deserializovat odpovědi na objekty jazyka C# silného typu, použijte PutAsJsonAsync rozšiřující metodu, která je součástí balíčku 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 }
}

Předchozí kód:

  • Serializuje Todo instanci jako JSON a odešle PUT požadavek na "https://jsonplaceholder.typicode.com/todos/5".
  • Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
  • Deserializuje tělo odpovědi do Todo instance a zapíše do Todo konzoly.

Oprava HTTP

Požadavek PATCH je částečná aktualizace existujícího prostředku. Nevytáčí nový prostředek a není určený k nahrazení existujícího prostředku. Místo toho aktualizuje prostředek pouze částečně. Pokud chcete vytvořit požadavek HTTP PATCH s použitím identifikátoru HttpClient URI, použijte metodu 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
    //   }
}

Předchozí kód:

  • StringContent Připraví instanci s textem JSON požadavku (typ "application/json"MIME).
  • PATCH Odešle požadavek na "https://jsonplaceholder.typicode.com/todos/1".
  • Zajišťuje, že odpověď proběhne úspěšně, a zapíše do konzoly podrobnosti požadavku a text odpovědi JSON.

Pro požadavky v System.Net.Http.Json balíčku NuGet neexistují PATCH žádné metody rozšíření.

Odstranění HTTP

Požadavek DELETE odstraní existující prostředek. DELETE Požadavek je idempotentní, ale není bezpečný, což znamená, že více DELETE požadavků na stejné prostředky přináší stejný výsledek, ale požadavek ovlivňuje stav prostředku. Pokud chcete vytvořit požadavek HTTP DELETE s použitím identifikátoru HttpClient URI, použijte metodu 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
    //   {}
}

Předchozí kód:

  • DELETE Odešle požadavek na "https://jsonplaceholder.typicode.com/todos/1".
  • Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.

Tip

Odpověď na DELETE požadavek (stejně jako PUT požadavek) může nebo nemusí obsahovat text.

Hlavička HTTP

Požadavek HEAD je podobný GET požadavku. Místo vrácení prostředku vrátí pouze hlavičky přidružené k prostředku. Odpověď na HEAD požadavek nevrací tělo. Pokud chcete vytvořit požadavek HTTP HEAD s daným identifikátorem HttpClient URI, použijte HttpClient.SendAsync metodu s nastavenou HttpMethod HttpMethod.Headhodnotou :

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
}

Předchozí kód:

  • HEAD Odešle požadavek na "https://www.example.com/".
  • Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
  • Iteruje všechny hlavičky odpovědi a zapisuje je do konzoly.

Možnosti PROTOKOLU HTTP

Požadavek OPTIONS slouží k identifikaci metod HTTP, které server nebo koncový bod podporuje. Pokud chcete vytvořit požadavek HTTP OPTIONS s daným identifikátorem HttpClient URI, použijte HttpClient.SendAsync metodu s nastavenou HttpMethod HttpMethod.Optionshodnotou :

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
}

Předchozí kód:

  • OPTIONS Odešle požadavek HTTP na "https://www.example.com/"adresu .
  • Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
  • Iteruje přes všechny hlavičky obsahu odpovědi a každý z nich zapisuje do konzoly.

Trasování HTTP

Požadavek TRACE může být užitečný pro ladění, protože poskytuje smyčku na úrovni aplikace zpět zprávy požadavku. Pokud chcete vytvořit požadavek HTTP TRACE , vytvořte pomocí HttpRequestMessage příkazu HttpMethod.Trace:

using HttpRequestMessage request = new(
    HttpMethod.Trace, 
    "{ValidRequestUri}");

Upozornění

Metoda TRACE HTTP není podporována všemi servery HTTP. Pokud se používá nechtěně, může vystavit ohrožení zabezpečení. Další informace naleznete v tématu Open Web Application Security Project (OWASP): Trasování mezi weby.

Zpracování odpovědi HTTP

Pokaždé, když zpracováváte odpověď HTTP, komunikujete s typem HttpResponseMessage . Při vyhodnocování platnosti odpovědi se používá několik členů. Stavový kód HTTP je k dispozici prostřednictvím HttpResponseMessage.StatusCode vlastnosti. Představte si, že jste odeslali požadavek na instanci klienta:

using HttpResponseMessage response = await httpClient.SendAsync(request);

Abyste měli jistotu response , že je OK (stavový kód HTTP 200), můžete ho vyhodnotit, jak je znázorněno v následujícím příkladu:

if (response is { StatusCode: HttpStatusCode.OK })
{
    // Omitted for brevity...
}

Existují další stavové kódy HTTP, které představují úspěšnou odpověď, například CREATED (stavový kód HTTP 201), ACCEPTED (stavový kód HTTP 202), NO CONTENT (stavový kód HTTP 204) a RESET CONTENT (stavový kód HTTP 205). Vlastnost můžete použít HttpResponseMessage.IsSuccessStatusCode také k vyhodnocení těchto kódů, což zajišťuje, že stavový kód odpovědi je v rozsahu 200–299:

if (response.IsSuccessStatusCode)
{
    // Omitted for brevity...
}

Pokud potřebujete, aby architektura vyvolá HttpRequestException, můžete volat metodu HttpResponseMessage.EnsureSuccessStatusCode() :

response.EnsureSuccessStatusCode();

Tento kód vyvolá HttpRequestException stavový kód odpovědi v rozsahu 200–299.

Platné odpovědi http na obsah

S platnou odpovědí můžete získat přístup k textu odpovědi pomocí Content vlastnosti. Tělo je k dispozici jako HttpContent instance, kterou můžete použít pro přístup k textu jako stream, bajtové pole nebo řetězec:

await using Stream responseStream =
    await response.Content.ReadAsStreamAsync();

V předchozím kódu responseStream se dá použít ke čtení textu odpovědi.

byte[] responseByteArray = await response.Content.ReadAsByteArrayAsync();

V předchozím kódu responseByteArray se dá použít ke čtení textu odpovědi.

string responseString = await response.Content.ReadAsStringAsync();

V předchozím kódu responseString se dá použít ke čtení textu odpovědi.

Když konečně víte, že koncový bod HTTP vrátí JSON, můžete tělo odpovědi deserializovat do libovolného platného objektu C# pomocí balíčku NuGet System.Net.Http.Json :

T? result = await response.Content.ReadFromJsonAsync<T>();

V předchozím kódu result je tělo odpovědi deserializováno jako typ T.

Zpracování chyb HTTP

Pokud požadavek HTTP selže, vyvolá se HttpRequestException . Zachycení samotné výjimky nemusí být dostatečné, protože existují další potenciální výjimky, které byste mohli chtít zvážit. Volající kód mohl například použít token zrušení, který byl zrušen před dokončením požadavku. V tomto scénáři byste zachytili 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}");
}

Podobně platí, že pokud při vytváření požadavku HTTP server nereaguje před HttpClient.Timeout překročením stejné výjimky, vyvolá se stejná výjimka. V tomto scénáři však můžete rozlišit, že došlo k vypršení časového limitu Exception.InnerException vyhodnocením při zachycení 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}");
}

Pokud v předchozím kódu došlo k vypršení časového limitu vnitřní výjimky TimeoutException a požadavek nebyl zrušen tokenem zrušení.

Pokud chcete vyhodnotit stavový kód HTTP při zachytávání HttpRequestException, můžete tuto vlastnost vyhodnotit 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}");
}

V předchozím kódu je volána metoda vyvolá EnsureSuccessStatusCode() výjimku, pokud odpověď není úspěšná. Vlastnost HttpRequestException.StatusCode se pak vyhodnotí a určí, jestli odpověď byla 404 (stavový kód HTTP 404). Existuje několik pomocných metod HttpClient , které implicitně volají EnsureSuccessStatusCode vaším jménem, zvažte následující rozhraní API:

Tip

Všechny HttpClient metody používané k provádění požadavků HTTP, které nevrací HttpResponseMessage implicitně volání EnsureSuccessStatusCode vaším jménem.

Při volání těchto metod můžete zpracovat HttpRequestException a vyhodnotit HttpRequestException.StatusCode vlastnost k určení stavového kódu HTTP odpovědi:

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}");
}

Můžou existovat scénáře, ve kterých potřebujete v kódu vyvolat HttpRequestException kód. Konstruktor HttpRequestException() je veřejný a můžete ho použít k vyvolání výjimky s vlastní zprávou:

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}");
}

Proxy server HTTP

Proxy server HTTP je možné nakonfigurovat jedním ze dvou způsobů. Pro vlastnost je zadána HttpClient.DefaultProxy výchozí hodnota. Případně můžete pro vlastnost zadat proxy HttpClientHandler.Proxy server.

Globální výchozí proxy server

Jedná se HttpClient.DefaultProxy o statickou vlastnost, která určuje výchozí proxy server, který všechny HttpClient instance používají, pokud není v předaném konstruktoru HttpClientHandler explicitně nastaven žádný proxy server.

Výchozí instance vrácená touto vlastností inicializuje následující jinou sadu pravidel v závislosti na vaší platformě:

  • Pro Windows: Načte konfiguraci proxy serveru z proměnných prostředí nebo pokud nejsou definovány, z nastavení proxy serveru uživatele.
  • Pro macOS: Načte konfiguraci proxy serveru z proměnných prostředí nebo pokud nejsou definované, z nastavení proxy serveru systému.
  • Pro Linux: Načte konfiguraci proxy serveru z proměnných prostředí nebo v případě, že nejsou definovány, tato vlastnost inicializuje nekonfigurovanou instanci, která obchází všechny adresy.

Proměnné prostředí používané k DefaultProxy inicializaci na platformách se systémem Windows a Unix jsou:

  • HTTP_PROXY: proxy server použitý pro požadavky HTTP.
  • HTTPS_PROXY: proxy server používaný na žádostech HTTPS.
  • ALL_PROXY: Proxy server používaný v požadavcích HTTP a/nebo HTTPS v případě HTTP_PROXY , že nejsou definovány nebo HTTPS_PROXY nejsou definovány.
  • NO_PROXY: Čárkami oddělený seznam názvů hostitelů, které by měly být vyloučeny z proxy serveru. Hvězdičky se nepodporují u zástupných znaků; pro případ, že chcete shodovat subdoménu, použijte úvodní tečku. Příklady: NO_PROXY=.example.com (s úvodní tečkou) se shodují www.example.com, ale nebudou se shodovat example.com. NO_PROXY=example.com (bez úvodní tečky) se neshoduje www.example.com. Toto chování se může v budoucnu znovu vrátit, aby se lépe shodovaly s jinými ekosystémy.

V systémech, kde proměnné prostředí rozlišují malá a velká písmena, mohou být názvy proměnných malými nebo velkými písmeny. Nejdřív se zaškrtnou malá písmena.

Proxy server může být název hostitele nebo IP adresa, případně za ním dvojtečka a číslo portu, nebo to může být http adresa URL, volitelně včetně uživatelského jména a hesla pro ověření proxy serveru. Adresa URL musí začínat písmenem http, nikoli httpsa nesmí obsahovat žádný text za názvem hostitele, IP adresou nebo portem.

Proxy na klienta

Vlastnost HttpClientHandler.Proxy identifikuje objekt, který WebProxy se má použít ke zpracování požadavků na internetové prostředky. Chcete-li určit, že se nemá použít žádný proxy server, nastavte Proxy vlastnost na instanci proxy vrácenou metodou GlobalProxySelection.GetEmptyWebProxy() .

Konfigurační soubor místního počítače nebo aplikace může určovat, že se používá výchozí proxy server. Pokud je zadaná vlastnost Proxy, přepíší nastavení proxy z vlastnosti Proxy místní počítač nebo konfigurační soubor aplikace a obslužná rutina použije zadané nastavení proxy serveru. Pokud není v konfiguračním souboru zadán žádný proxy server a vlastnost Proxy není zadána, obslužná rutina použije nastavení proxy serveru zděděné z místního počítače. Pokud neexistují žádná nastavení proxy serveru, požadavek se odešle přímo na server.

Třída HttpClientHandler parsuje seznam obejití proxy serveru se zástupnými znaky zděděnými z nastavení místního počítače. Třída například HttpClientHandler parsuje seznam obejití "nt*" z prohlížečů jako regulární výraz "nt.*". Adresa URL http://nt.com proxy by tedy obešla pomocí HttpClientHandler třídy.

Třída HttpClientHandler podporuje obejití místního proxy serveru. Třída považuje cíl za místní, pokud jsou splněny některé z následujících podmínek:

  1. Cíl obsahuje plochý název (v adrese URL nejsou žádné tečky).
  2. Cíl obsahuje adresu zpětné smyčky (Loopback nebo IPv6Loopback) nebo cíl obsahuje přiřazenou IPAddress k místnímu počítači.
  3. Přípona domény cíle odpovídá příponě domény místního počítače (DomainName).

Další informace o konfiguraci proxy serveru najdete v tématech:

Viz také