Sdílet prostřednictvím


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í třídy HttpClient.

Důležité

Všechny ukázkové požadavky HTTP v tomto článku 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. Volitelné System.Net.Http.Json balíčku NuGet poskytuje několik rozšiřujících metod pro HttpClient a HttpContent objekty, které provádějí automatickou serializaci a deserializaci pomocí balíčku NuGet 📦 System.Text.Json. Příklady v tomto článku upozorní na místa, kde jsou tato rozšíření k dispozici.

Tip

Veškerý zdrojový kód, na který odkazuje tento článek, je k dispozici v úložišti GitHubu: Dokumentace .NET.

Vytvoření objektu HttpClient

Většina příkladů v tomto článku opakovaně používá stejnou instanci HttpClient, abyste mohli instanci nakonfigurovat jednou a použít ji pro zbývající příklady. Chcete-li vytvořit objekt HttpClient, použijte konstruktor třídy HttpClient. Další informace naleznete v tématu Pokyny pro použití 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"),
};

Kód dokončí následující úlohy:

  • Vytvořte novou instanci HttpClient jako proměnnou static. Podle pokynů doporučujeme opakovaně používat HttpClient instance během životního cyklu aplikace.
  • Nastavte vlastnost HttpClient.BaseAddress na "https://jsonplaceholder.typicode.com".

Tato instance HttpClient používá základní adresu k provádění následných požadavků. Pokud chcete použít další konfigurace, zvažte následující rozhraní API:

Tip

Alternativně můžete vytvořit HttpClient instance pomocí přístupu se vzorem 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 Továrna na HTTP klienty v .NET.

Vytvoření požadavku HTTP

Pokud chcete vytvořit požadavek HTTP, zavoláte některou z následujících metod 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

požadavek USER SPECIFIED indikuje, že metoda SendAsync přijímá všechny platné HttpMethod objekt.

Varování

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

Poznámka:

Při cílení na zařízení s Androidem (například s vývojem rozhraní .NET MAUI) musíte do oddílu <application></application> v souboru AndroidManifest.xml přidat definici android:usesCleartextTraffic="true". Toto nastavení umožňuje přenosy s vymazáním textu, jako jsou požadavky HTTP, které jsou jinak zakázané 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 prostého textu pro doménu localhost.

Principy obsahu 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 (POST, PUT, PATCH), použijete třídu HttpContent 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 je také používána k reprezentaci těla odpovědi třídy HttpResponseMessage, které je přístupné přes vlastnost HttpResponseMessage.Content.

Použití požadavku HTTP GET

Požadavek GET by neměl posílat tělo. Tento požadavek se používá (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 vzhledem k instanci HttpClient a objektu 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
    //   }
}

Kód dokončí následující úlohy:

  • Vytvořte GET požadavek na koncový bod "https://jsonplaceholder.typicode.com/todos/3".
  • Ujistěte se, že odpověď proběhla úspěšně.
  • Napište podrobnosti žádosti do konzoly.
  • Přečtěte si text odpovědi jako řetězec.
  • Napište text odpovědi JSON do konzoly.

Metoda WriteRequestToConsole je vlastní rozšíření, které není součástí architektury. Pokud vás zajímá implementace, 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>

Například požadavek GET na koncový bod "https://jsonplaceholder.typicode.com/todos/3" zobrazí následující zprávu:

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

Vytvoření požadavku HTTP GET z JSON

Koncový bod https://jsonplaceholder.typicode.com/todos vrátí pole JSON s objekty Todo. Jejich struktura JSON se podobá následující podobě:

[
  {
    "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 vlastnostmi record class, Id, Title, Completed a UserId. 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 na objekt jazyka C# silného typu, použijte metodu rozšíření GetFromJsonAsync, 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 }
}

Kód dokončí následující úlohy:

  • Vytvořte GET žádost na "https://jsonplaceholder.typicode.com/todos?userId=1&completed=false".

    Řetězec dotazu představuje kritéria filtrování požadavku. Když příkaz proběhne úspěšně, odpověď se automaticky deserializuje do objektu List<Todo>.

  • Zapište podrobnosti žádosti do konzoly spolu s každým objektem Todo.

Použití požadavku HTTP POST

Požadavek POST odešle data na server ke zpracování. Hlavička Content-Type požadavku označuje, jaký MIME typ text odesílá. Pokud chcete vytvořit požadavek http POST vzhledem k instanci HttpClient a objektu Uri, použijte metodu 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
    //   }
}

Kód dokončí následující úlohy:

  • Připravte instanci StringContent s textem JSON požadavku (typ MIME "application/json").
  • Na koncový bod "https://jsonplaceholder.typicode.com/todos" vytvořte POST požadavek.
  • Ujistěte se, že odpověď proběhla úspěšně, a zapište podrobnosti požadavku do konzoly.
  • Napište text odpovědi jako řetězec do konzoly.

Vytvoření požadavku HTTP POST ve formátu JSON

K automatickému serializování argumentů požadavku POST a deserializaci odpovědí na silně typované objekty v jazyce C# použijte rozšiřující metodu PostAsJsonAsync dostupnou v 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 }
}

Kód dokončí následující úlohy:

  • Serializujte instanci Todo do formátu JSON a proveďte POST požadavek k bodu "https://jsonplaceholder.typicode.com/todos".
  • Ujistěte se, že odpověď proběhla úspěšně, a zapište podrobnosti požadavku do konzoly.
  • Deserializovat tělo odpovědi do Todo instance a zapsat Todo objekt do konzoly.

Použití požadavku HTTP PUT

Metoda požadavku PUT buď nahradí existující prostředek, nebo vytvoří nový pomocí datové části textu požadavku. Pokud chcete vytvořit požadavek http PUT vzhledem k instanci HttpClient a objektu 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
    //   }
}

Kód dokončí následující úlohy:

  • Připravte instanci StringContent s textem JSON požadavku (typ MIME "application/json").
  • Odešlete požadavek PUT na server "https://jsonplaceholder.typicode.com/todos/1".
  • Ujistěte se, že je odpověď úspěšná, a zapište podrobnosti požadavku s textem odpovědi JSON do konzoly.

Vytvoření požadavku HTTP PUT jako JSON

Pokud chcete PUT argumenty požadavku automaticky serializovat a odpovědi deserializovat na silně typované objekty jazyka C#, použijte rozšiřující metodu PutAsJsonAsync, 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 }
}

Kód dokončí následující úlohy:

  • Serializujte instanci Todo jako JSON a proveďte PUT požadavek na koncový bod "https://jsonplaceholder.typicode.com/todos/5".
  • Ujistěte se, že odpověď proběhla úspěšně, a zapište podrobnosti požadavku do konzoly.
  • Deserializujte tělo odpovědi do instance Todo a zapište objekty Todo do konzoly.

Použijte požadavek HTTP PATCH

PATCH požadavek představuje částečnou aktualizaci stávajícího zdroje. Tento požadavek nevytvoří nový prostředek a není určen k nahrazení existujícího prostředku. Místo toho tato metoda pouze částečně aktualizuje prostředek. Pokud chcete vytvořit požadavek http PATCH vzhledem k instanci HttpClient a objektu 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
    //   }
}

Kód dokončí následující úlohy:

  • Připravte instanci StringContent s textem JSON požadavku (typ MIME "application/json").
  • Vytvořte PATCH požadavek na endpoint "https://jsonplaceholder.typicode.com/todos/1".
  • Ujistěte se, že je odpověď úspěšná, a zapište podrobnosti požadavku s textem odpovědi JSON do konzoly.

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

Použití požadavku HTTP DELETE

Požadavek DELETE odebere existující prostředek a požadavek je idempotentní, ale ne bezpečný. Více DELETE požadavků na stejné prostředky přináší stejný výsledek, ale požadavek má vliv na stav prostředku. Pokud chcete vytvořit požadavek http DELETE vzhledem k instanci HttpClient a objektu 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
    //   {}
}

Kód dokončí následující úlohy:

  • Vytvořte DELETE požadavek na endpoint "https://jsonplaceholder.typicode.com/todos/1".
  • Ujistěte se, že odpověď proběhla úspěšně, a zapište podrobnosti požadavku do konzoly.

Tip

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

Prozkoumání požadavku HTTP HEAD

Požadavek HEAD je podobný GET požadavku. Místo vrácení prostředku tento požadavek 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 vzhledem k instanci HttpClient a objektu Uri, použijte metodu HttpClient.SendAsync s typem HttpMethod nastaveným 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
}

Kód dokončí následující úlohy:

  • Proveďte žádost typu HEAD na koncový bod "https://www.example.com/".
  • Ujistěte se, že odpověď proběhla úspěšně, a zapište podrobnosti požadavku do konzoly.
  • Iterujte všechny hlavičky odpovědi a zapište každou hlavičku do konzoly.

Prozkoumání požadavku HTTP OPTIONS

Požadavek OPTIONS slouží k identifikaci metod HTTP, které server nebo koncový bod podporuje. Pokud chcete vytvořit požadavek HTTP OPTIONS vzhledem k instanci HttpClient a objektu Uri, použijte metodu HttpClient.SendAsync s typem HttpMethod nastaveným 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
}

Kód dokončí následující úlohy:

  • Odešlete HTTP požadavek OPTIONS na koncový bod "https://www.example.com/".
  • Ujistěte se, že odpověď proběhla úspěšně, a zapište podrobnosti požadavku do konzoly.
  • Iterujte všechny hlavičky obsahu odpovědi a zapište každou hlavičku do konzoly.

Prozkoumání požadavku HTTP TRACE

Požadavek TRACE může být užitečný pro ladění, protože poskytuje zpětné spojení na úrovni aplikace požadavek zprávy. Pokud chcete vytvořit požadavek http TRACE, vytvořte HttpRequestMessage pomocí typu HttpMethod.Trace:

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

Upozornění

Ne všechny servery HTTP podporují metodu TRACE HTTP. Tato metoda může vystavit ohrožení zabezpečení, pokud se používá nechtěně. Pro více informací se podívejte na Open Web Application Security Project (OWASP): Cross Site Tracing.

Zpracování odpovědi HTTP

Při zpracování odpovědi HTTP komunikujete s typem HttpResponseMessage. K vyhodnocení platnosti odpovědi se používá několik členů. Stavový kód HTTP je k dispozici ve vlastnosti HttpResponseMessage.StatusCode.

Dejme tomu, že odešlete požadavek pomocí instance klienta:

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

K zajištění, že response je OK (stavový kód HTTP 200), můžete ověřit hodnotu, jak ukazuje následující příklad:

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 framework vyvolal HttpRequestException chybu, můžete zavolat metodu HttpResponseMessage.EnsureSuccessStatusCode().

response.EnsureSuccessStatusCode();

Tento kód vyvolá chybu HttpRequestException, pokud stavový kód odpovědi není v rozsahu 200–299.

Prozkoumejte platné obsahové odpovědi HTTP

Pomocí platné odpovědi můžete získat přístup k textu odpovědi pomocí vlastnosti Content. Tělo zprávy je k dispozici jako instance HttpContent, kterou můžete použít pro přístup k tělu jako datový proud, bajtové pole nebo řetězec.

Následující kód používá objekt responseStream ke čtení textu odpovědi:

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

Ke čtení textu odpovědi můžete použít různé objekty. Ke čtení textu odpovědi použijte objekt responseByteArray:

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

Ke čtení textu odpovědi použijte objekt responseString:

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

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

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

V tomto kódu je hodnota result, která představuje tělo odpovědi, deserializována jako typ T.

Použití zpracování chyb HTTP

Když požadavek HTTP selže, systém vyvolá objekt HttpRequestException. Pouhé zachycení výjimky nemusí být dostatečné. Existují další potenciální výjimky, které byste mohli chtít zvážit. Volající kód může například použít token zrušení, který byl zrušen před dokončením požadavku. V tomto scénáři můžete zachytit chybu 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 když provedete požadavek HTTP, pokud server neodpoví před překročením hodnoty HttpClient.Timeout, vyvolá se stejná výjimka. V tomto scénáři můžete rozlišit, že došlo k vypršení časového limitu vyhodnocením vlastnosti Exception.InnerException při zachycení chyby 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 je vnitřní výjimka v kódu typu TimeoutException, došlo k vypršení časového limitu a token zrušení požadavek nezruší.

Pokud chcete vyhodnotit stavový kód HTTP při zachycení objektu HttpRequestException, můžete vyhodnotit vlastnost 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 kódu se volá metoda EnsureSuccessStatusCode(), která vyvolá výjimku, pokud odpověď není úspěšná. Vlastnost HttpRequestException.StatusCode se pak vyhodnotí a určí, jestli odpověď byla 404 (stavový kód HTTP 404). V objektu HttpClient existuje několik pomocných metod, které implicitně volají metodu EnsureSuccessStatusCode vaším jménem.

Pro řešení chyb HTTP zvažte následující rozhraní API:

Tip

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

Při volání těchto metod můžete zpracovat objekt HttpRequestException a vyhodnotit vlastnost HttpRequestException.StatusCode, abyste určili stavový kód 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 se zde vyskytovat situace, kdy potřebujete v kódu vyvolat objekt HttpRequestException. 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}");
}

Konfigurace proxy serveru 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.

Použití globálního výchozího proxy serveru

Vlastnost HttpClient.DefaultProxy je statická vlastnost, která určuje výchozí proxy server, který používají všechny HttpClient instance, pokud není v objektu HttpClientHandler předán prostřednictvím jeho konstruktoru explicitně žádný proxy server.

Výchozí instance vrácená touto vlastností inicializuje podle jiné sady pravidel v závislosti na vaší platformě:

  • Windows: Přečtěte konfiguraci proxy serveru z proměnných prostředí, a pokud nejsou tyto proměnné definovány, přečtěte ji z uživatelského nastavení proxy.
  • macOS: Čtení konfigurace proxy serveru z proměnných prostředí, nebo pokud nejsou definovány, z nastavení systémového proxy serveru.
  • Linux: Čtení konfigurace proxy serveru z proměnných prostředí, nebo pokud proměnné nejsou definovány, inicializovat nekonfigurovanou instanci tak, aby byly všechny adresy obejity.

Inicializace vlastností DefaultProxy na platformách se systémem Windows a Unix používá následující proměnné prostředí:

  • HTTP_PROXY: Proxy server použitý pro požadavky HTTP.
  • HTTPS_PROXY: Proxy server použitý na žádostech HTTPS.
  • ALL_PROXY: Proxy server použitý v požadavcích HTTP a/nebo HTTPS, pokud nejsou definovány proměnné HTTP_PROXY nebo HTTPS_PROXY.
  • NO_PROXY: Seznam názvů hostitelů oddělených čárkami, které se mají vyloučit z proxy serveru. Hvězdičky nejsou u zástupných znaků podporované. Pokud chcete shodovat subdoménu, použijte úvodní tečku (.). Příklady: .NO_PROXY=.example.com (s počáteční tečkou) odpovídá www.example.com, ale neodpovídá example.com. NO_PROXY=example.com (bez úvodní tečky) neodpovídá 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 napsány malými nebo velkými písmeny. Nejdřív se zkontrolují malá písmena v názvech.

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 adresa URL http, volitelně včetně uživatelského jména a hesla pro ověření proxy serveru. Adresa URL musí začínat http, nikoli https, a nesmí obsahovat žádný text za názvem hostitele, IP adresou nebo portem.

Konfigurace proxy serveru na klienta

Vlastnost HttpClientHandler.Proxy identifikuje objekt WebProxy, který 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 zadána vlastnost Proxy, nastavení proxy serveru z vlastnosti Proxy přepíše konfigurační soubor místního počítače nebo aplikace a obslužná rutina použije zadaná nastavení proxy. Pokud v konfiguračním souboru není zadaný žádný proxy server a není zadána vlastnost Proxy, 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. Například třída HttpClientHandler zpracovává seznam obejití "nt*" z prohlížečů vyjádřený jako regulární výraz "nt.*". Proto adresa URL http://nt.com obchází proxy pomocí třídy HttpClientHandler.

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:

  • Cíl obsahuje plochý název (bez tečk (.) v adrese URL).
  • Cíl obsahuje adresu zpětné smyčky (Loopback nebo IPv6Loopback) nebo cíl obsahuje IPAddress vlastnost přiřazenou místnímu počítači.
  • Přípona domény cíle odpovídá příponě domény místního počítače, jak je definováno v DomainName vlastnosti.

Další informace o konfiguraci proxy serveru najdete v následujících rozhraních API:

Další kroky