HttpClient sınıfıyla HTTP istekleri yapma

Bu makalede, HTTP istekleri yapmayı ve sınıfıyla yanıtları işlemeyi HttpClient öğreneceksiniz.

Önemli

Örnek HTTP isteklerinin tümü aşağıdaki URL'lerden birini hedefler:

HTTP uç noktaları genellikle JavaScript Nesne Gösterimi (JSON) verilerini döndürür, ancak her zaman döndürmez. Kolaylık olması için, isteğe bağlı System.Net.Http.Json NuGet paketi ve için HttpContentHttpClient kullanarak otomatik serileştirme ve seri durumdan çıkarma System.Text.Jsongerçekleştiren çeşitli uzantı yöntemleri sağlar. İzleyen örnekler, bu uzantıların kullanılabildiği yerlere dikkat çekmektedir.

İpucu

Bu makaledeki tüm kaynak kodu GitHub: .NET Docs deposunda bulabilirsiniz.

Oluşturma HttpClient

Aşağıdaki örneklerin çoğu aynı HttpClient örneği yeniden kullandığından yalnızca bir kez yapılandırılması gerekir. oluşturmak HttpClientiçin sınıf oluşturucuyu HttpClient kullanın. Daha fazla bilgi için bkz . HttpClient kullanma yönergeleri.

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

Yukarıdaki kod:

  • Yeni HttpClient bir örneği değişken olarak başlatır static . Yönergelere göre, uygulamanın yaşam döngüsü boyunca örneklerin yeniden kullanılması HttpClient önerilir.
  • öğesini olarak HttpClient.BaseAddress"https://jsonplaceholder.typicode.com"ayarlar.

Bu HttpClient örnek, sonraki istekleri yaparken temel adresi kullanır. Diğer yapılandırmaları uygulamak için şunları göz önünde bulundurun:

İpucu

Alternatif olarak, istediğiniz sayıda istemciyi yapılandırmanıza ve bunları bağımlılık ekleme hizmetleri olarak kullanmanıza olanak tanıyan bir fabrika düzeni yaklaşımı kullanarak örnekler oluşturabilirsiniz HttpClient . Daha fazla bilgi için bkz . .NET ile HTTP istemci fabrikası.

HTTP isteğinde bulunma

HTTP isteğinde bulunmak için aşağıdaki API'lerden herhangi birini çağırırsınız:

HTTP yöntemi 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 isteği, yöntemin SendAsync geçerli HttpMethodbir kabul ettiğini gösterir.

Uyarı

HTTP isteklerinde bulunmak ağ G/Ç'ye bağlı iş olarak kabul edilir. Zaman uyumlu HttpClient.Send bir yöntem olsa da, bunu yapmak için iyi bir nedeniniz yoksa, bunun yerine zaman uyumsuz API'leri kullanmanız önerilir.

HTTP içeriği

Türü HttpContent , bir HTTP varlık gövdesini ve ilgili içerik üst bilgilerini temsil etmek için kullanılır. Gövde, POST, PUTve PATCHgerektiren HTTP yöntemleri (veya istek yöntemleri) için, isteğin HttpContent gövdesini belirtmek için sınıfını kullanırsınız. Çoğu örnek, alt sınıfın StringContent bir JSON yüküyle nasıl hazırlayacağını gösterir, ancak farklı içerik (MIME) türleri için başka alt sınıflar vardır.

HttpContent sınıfı, özelliğinde HttpResponseMessage.Content erişilebilen yanıt gövdesini HttpResponseMessagetemsil etmek için de kullanılır.

HTTP Al

İstek GET bir gövde göndermemelidir ve bir kaynaktan veri almak (veya almak) için kullanılır (yöntem adından da belirtildiği gibi). bir ve URI'sine sahip bir HttpClient HTTP GET isteğinde bulunmak için yöntemini kullanınHttpClient.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
    //   }
}

Yukarıdaki kod:

  • adresine "https://jsonplaceholder.typicode.com/todos/3"bir GET istekte bulunur.
  • Yanıtın başarılı olmasını sağlar.
  • İstek ayrıntılarını konsola yazar.
  • Yanıt gövdesini dize olarak okur.
  • JSON yanıt gövdesini konsola yazar.

WriteRequestToConsole, çerçevenin parçası olmayan özel bir uzantı yöntemidir, ancak nasıl uygulandığını merak ediyorsanız aşağıdaki C# kodunu göz önünde bulundurun:

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

Bu işlevsellik, istek ayrıntılarını konsola aşağıdaki biçimde yazmak için kullanılır:

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

Örneğin, isteği https://jsonplaceholder.typicode.com/todos/3 aşağıdaki GET iletiyi döndürür:

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

JSON'dan HTTP Alma

https://jsonplaceholder.typicode.com/todos nokta, "todo" nesnelerinden oluşan bir JSON dizisi döndürür. JSON yapıları aşağıdakine benzer:

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

C# Todo nesnesi aşağıdaki gibi tanımlanır:

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

İsteğe bağlı Id, , TitleCompletedve UserId özelliklerine sahip bir record class tür. Tür hakkında record daha fazla bilgi için bkz . C# dilinde kayıt türlerine giriş. İstekleri otomatik olarak seri durumdan GET çıkararak kesin türdeki C# nesnesine getirmek için System.Net.Http.Json NuGet paketinin parçası olan uzantı yöntemini kullanınGetFromJsonAsync.

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

Önceki kodda:

  • GET öğesine bir istek yapılır"https://jsonplaceholder.typicode.com/todos?userId=1&completed=false".
    • Sorgu dizesi, isteğin filtreleme ölçütlerini temsil eder.
  • Yanıt, başarılı olduğunda otomatik olarak seri List<Todo> durumdan çıkarılır.
  • İstek ayrıntıları, her Todo nesneyle birlikte konsola yazılır.

HTTP Gönderisi

İstek POST , işlenmek üzere sunucuya veri gönderir. Content-Type İsteğin üst bilgisi, gövdenin gönderdiği MIME türünü gösterir. ve Uriverilen HttpClient bir HTTP POST isteğinde bulunmak için yöntemini kullanınHttpClient.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
    //   }
}

Yukarıdaki kod:

  • İsteğin JSON gövdesine (MIME türü"application/json") sahip bir StringContent örneği hazırlar.
  • adresine "https://jsonplaceholder.typicode.com/todos"bir POST istekte bulunur.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını konsola yazar.
  • Yanıt gövdesini konsola dize olarak yazar.

JSON olarak HTTP Gönderisi

İstek bağımsız değişkenlerini otomatik olarak seri hale POST getirmek ve yanıtları kesin türü belirlenmiş C# nesnelerine seri durumdan çıkarmak için System.Net.Http.Json NuGet paketinin parçası olan uzantı yöntemini kullanınPostAsJsonAsync.

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

Yukarıdaki kod:

  • Örneği JSON olarak seri hale Todo getirir ve isteğinde "https://jsonplaceholder.typicode.com/todos"bulunurPOST.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını konsola yazar.
  • Yanıt gövdesini bir Todo örneğe seri durumdan çıkartır Todo ve konsola yazar.

HTTP Put

PUT İstek yöntemi mevcut bir kaynağın yerini alır veya istek gövdesi yükünü kullanarak yeni bir kaynak oluşturur. bir ve URI'sine sahip bir HttpClient HTTP PUT isteğinde bulunmak için yöntemini kullanınHttpClient.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
    //   }
}

Yukarıdaki kod:

  • İsteğin JSON gövdesine (MIME türü"application/json") sahip bir StringContent örneği hazırlar.
  • adresine "https://jsonplaceholder.typicode.com/todos/1"bir PUT istekte bulunur.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını ve JSON yanıt gövdesini konsola yazar.

JSON olarak HTTP Put

İstek bağımsız değişkenlerini otomatik olarak seri hale PUT getirmek ve yanıtları kesin olarak yazılan C# nesnelerine seri durumdan çıkarmak için System.Net.Http.Json NuGet paketinin parçası olan uzantı yöntemini kullanınPutAsJsonAsync.

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

Yukarıdaki kod:

  • Örneği JSON olarak seri hale Todo getirir ve isteğinde "https://jsonplaceholder.typicode.com/todos/5"bulunurPUT.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını konsola yazar.
  • Yanıt gövdesini bir Todo örneğe seri durumdan çıkartır Todo ve konsola yazar.

HTTP Düzeltme Eki

İstek PATCH , var olan bir kaynağın kısmi bir güncelleştirmesidir. Yeni bir kaynak oluşturmaz ve mevcut bir kaynağın yerini almak için tasarlanmamıştır. Bunun yerine, bir kaynağı yalnızca kısmen güncelleştirir. bir ve URI'sine sahip bir HttpClient HTTP PATCH isteğinde bulunmak için yöntemini kullanınHttpClient.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
    //   }
}

Yukarıdaki kod:

  • İsteğin JSON gövdesine (MIME türü"application/json") sahip bir StringContent örneği hazırlar.
  • adresine "https://jsonplaceholder.typicode.com/todos/1"bir PATCH istekte bulunur.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını ve JSON yanıt gövdesini konsola yazar.

NuGet paketindeki System.Net.Http.Json istekler için PATCH uzantı yöntemi yok.

HTTP Silme

İstek DELETE var olan bir kaynağı siler. İstek DELETE bir kez etkili olur ancak güvenli değildir, yani aynı kaynaklara yönelik birden çok DELETE istek aynı sonucu verir, ancak istek kaynağın durumunu etkiler. bir ve URI'sine sahip bir HttpClient HTTP DELETE isteğinde bulunmak için yöntemini kullanınHttpClient.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
    //   {}
}

Yukarıdaki kod:

  • adresine "https://jsonplaceholder.typicode.com/todos/1"bir DELETE istekte bulunur.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını konsola yazar.

İpucu

bir DELETE isteğe yanıt (tıpkı bir PUT istek gibi) bir gövde içerebilir veya içermeyebilir.

HTTP Başlığı

İstek HEAD bir isteğe benzer GET . Kaynağı döndürmek yerine yalnızca kaynakla ilişkili üst bilgileri döndürür. İstek yanıtı HEAD bir gövde döndürmez. bir ve URI'sine sahip bir HttpClient HTTP HEAD isteğinde bulunmak için olarak ayarlanmış HttpMethod.Headyöntemi HttpMethod kullanınHttpClient.SendAsync:

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
}

Yukarıdaki kod:

  • adresine "https://www.example.com/"bir HEAD istekte bulunur.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını konsola yazar.
  • Tüm yanıt üst bilgilerini yineler ve her birini konsola yazar.

HTTP Seçenekleri

İstek OPTIONS , bir sunucunun veya uç noktanın hangi HTTP yöntemlerini desteklediğini belirlemek için kullanılır. bir ve URI'sine sahip bir HttpClient HTTP OPTIONS isteğinde bulunmak için olarak ayarlanmış HttpMethod.Optionsyöntemi HttpMethod kullanınHttpClient.SendAsync:

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
}

Yukarıdaki kod:

  • adresine "https://www.example.com/"bir OPTIONS HTTP isteği gönderir.
  • Yanıtın başarılı olmasını sağlar ve istek ayrıntılarını konsola yazar.
  • Tüm yanıt içeriği üst bilgilerini yineler ve her birini konsola yazar.

HTTP İzleme

İstek TRACE , istek iletisinde uygulama düzeyinde geri döngü sağladığından hata ayıklama için yararlı olabilir. HTTP TRACE isteğinde bulunmak için kullanarak bir HttpRequestMessageHttpMethod.Traceoluşturun:

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

Dikkat

TRACE HTTP yöntemi tüm HTTP sunucuları tarafından desteklenmez. Akıllıca kullanılmasa bir güvenlik açığı ortaya çıkarabilir. Daha fazla bilgi için bkz . Open Web Application Security Project (OWASP): Siteler Arası İzleme.

HTTP yanıtını işleme

Bir HTTP yanıtını her işlerken türüyle etkileşim kurarsınız HttpResponseMessage . Yanıtın geçerliliği değerlendirilirken birkaç üye kullanılır. HTTP durum kodu özelliği aracılığıyla HttpResponseMessage.StatusCode kullanılabilir. İstemci örneği için bir istek gönderdiğinizi düşünün:

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

değerinin responseOK (HTTP durum kodu 200) olduğundan emin olmak için, aşağıdaki örnekte gösterildiği gibi değerlendirebilirsiniz:

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

Başarılı bir yanıtı temsil eden (HTTP durum kodu 201), (HTTP durum kodu 202 NO CONTENT ), ACCEPTED (HTTP durum kodu 204) ve RESET CONTENT (HTTP durum kodu 205) gibi CREATED başka HTTP durum kodları da vardır. Bu kodları değerlendirmek için özelliğini de kullanabilirsiniz HttpResponseMessage.IsSuccessStatusCode ve bu da yanıt durum kodunun 200-299 aralığında olmasını sağlar:

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

Çerçevenin HttpRequestExceptionoluşturması gerekiyorsa yöntemini çağırabilirsiniz HttpResponseMessage.EnsureSuccessStatusCode() :

response.EnsureSuccessStatusCode();

Bu kod, yanıt durum kodu 200-299 aralığında değilse bir HttpRequestException oluşturur.

HTTP geçerli içerik yanıtları

Geçerli bir yanıtla, özelliğini kullanarak yanıt gövdesine Content erişebilirsiniz. Gövde, akış HttpContent , bayt dizisi veya dize olarak gövdeye erişmek için kullanabileceğiniz bir örnek olarak kullanılabilir:

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

Yukarıdaki kodda, responseStream yanıt gövdesini okumak için kullanılabilir.

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

Yukarıdaki kodda, responseByteArray yanıt gövdesini okumak için kullanılabilir.

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

Yukarıdaki kodda, responseString yanıt gövdesini okumak için kullanılabilir.

Son olarak, bir HTTP uç noktasının JSON döndürdüğünden emin olduğunuzda System.Net.Http.Json NuGet paketini kullanarak yanıt gövdesini geçerli bir C# nesnesine seri durumdan çıkarabilirsiniz:

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

Yukarıdaki kodda, result yanıt gövdesi türü Tolarak seri durumdan çıkarılır.

HTTP hata işleme

BIR HTTP isteği başarısız olduğunda, HttpRequestException oluşturulur. İşlemeyi göz önünde bulundurmanız gerekebilecek başka olası özel durumlar da olduğundan, bu özel durumun tek başına yakalanması yeterli olmayabilir. Örneğin, çağıran kod istek tamamlanmadan önce iptal edilmiş bir iptal belirteci kullanmış olabilir. Bu senaryoda, öğesini yakalarsınız 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}");
}

Benzer şekilde, HTTP isteğinde bulunurken, sunucu aşılana kadar HttpClient.Timeout yanıt vermezse aynı özel durum oluşturulur. Ancak bu senaryoda, zaman aşımının oluştuğundan, öğesini yakalarken TaskCanceledExceptionöğesini Exception.InnerException değerlendirerek ayırt edebilirsiniz:

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

Yukarıdaki kodda, iç özel durum zaman TimeoutException aşımı oluştuğunda ve istek iptal belirteci tarafından iptal edilmediğinde.

Bir HttpRequestExceptionyakalama sırasında HTTP durum kodunu değerlendirmek için özelliğini değerlendirebilirsiniz 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}");
}

Yukarıdaki kodda EnsureSuccessStatusCode() , yanıt başarılı olmazsa bir özel durum oluşturma yöntemi çağrılır. Ardından, yanıtın HttpRequestException.StatusCode bir 404 (HTTP durum kodu 404) olup olmadığını belirlemek için özelliği değerlendirilir. Sizin adınıza örtük olarak çağıran EnsureSuccessStatusCode birkaç yardımcı yöntem HttpClient vardır, aşağıdaki API'leri göz önünde bulundurun:

İpucu

Sizin adınıza örtük bir HttpResponseMessage çağrı EnsureSuccessStatusCode döndürmeyen HTTP isteklerinde bulunmak için kullanılan tüm HttpClient yöntemler.

Bu yöntemleri çağırırken, yanıtın HttpRequestException HTTP durum kodunu belirlemek için ve özelliğini işleyebilirsiniz HttpRequestException.StatusCode :

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

kodunuz içinde oluşturmanız HttpRequestException gereken senaryolar olabilir. HttpRequestException() Oluşturucu geneldir ve özel bir iletiyle özel durum oluşturmak için bunu kullanabilirsiniz:

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

HTTP proxy'si

HTTP proxy'si iki yoldan biriyle yapılandırılabilir. Özelliğinde HttpClient.DefaultProxy bir varsayılan belirtilir. Alternatif olarak, özelliğinde HttpClientHandler.Proxy bir proxy belirtebilirsiniz.

Genel varsayılan proxy

HttpClient.DefaultProxy, oluşturucusunda açıkça HttpClientHandler hiçbir ara sunucu ayarlanmadıysa tüm HttpClient örneklerin kullandığı varsayılan ara sunucuyu belirleyen statik bir özelliktir.

Bu özellik tarafından döndürülen varsayılan örnek, platformunuza bağlı olarak farklı bir kural kümesinden sonra başlatılır:

  • Windows için: Ortam değişkenlerinden veya bunlar tanımlanmamışsa kullanıcının proxy ayarlarından ara sunucu yapılandırmasını okur.
  • macOS için: Ortam değişkenlerinden veya tanımlanmamışsa sistemin proxy ayarlarından ara sunucu yapılandırmasını okur.
  • Linux için: Ortam değişkenlerinden ara sunucu yapılandırmasını okur veya bunların tanımlanmaması durumunda, bu özellik tüm adresleri atlayan yapılandırılmamış bir örneği başlatır.

Windows ve Unix tabanlı platformlarda başlatma için DefaultProxy kullanılan ortam değişkenleri şunlardır:

  • HTTP_PROXY: HTTP isteklerinde kullanılan proxy sunucusu.
  • HTTPS_PROXY: HTTPS isteklerinde kullanılan proxy sunucusu.
  • ALL_PROXY: ve/veya tanımlanmadığı durumlarda HTTP_PROXY HTTP ve/ HTTPS_PROXY veya HTTPS isteklerinde kullanılan proxy sunucusu.
  • NO_PROXY: Ara sunucu oluşturmanın dışında tutulması gereken ana bilgisayar adlarının virgülle ayrılmış listesi. Joker karakterler için yıldız işareti desteklenmez; bir alt etki alanıyla eşleştirmek istemeniz durumunda öndeki noktayı kullanın. Örnekler: NO_PROXY=.example.com (baştaki noktayla) ile eşleşecektir www.example.comancak eşleşmeyecektir example.com. NO_PROXY=example.com (baştaki nokta olmadan) ile eşleşmez www.example.com. Bu davranış gelecekte diğer ekosistemleri daha iyi eşleştirmek için yeniden ziyaret edilebilir.

Ortam değişkenlerinin büyük/küçük harfe duyarlı olduğu sistemlerde değişken adlarının tümü küçük harf veya tümü büyük harf olabilir. Önce küçük harf adları denetleniyor.

Ara sunucu, isteğe bağlı olarak iki nokta üst üste ve bağlantı noktası numarasıyla izlenen bir ana bilgisayar adı veya IP adresi olabileceği gibi, isteğe bağlı olarak proxy kimlik doğrulaması için kullanıcı adı ve parola da dahil olmak üzere bir http URL olabilir. URL, ile değil ile httpsbaşlamalıdır httpve konak adı, IP veya bağlantı noktasından sonra metin içeremez.

İstemci başına ara sunucu

özelliği, HttpClientHandler.Proxy İnternet kaynaklarına WebProxy yönelik istekleri işlemek için kullanılacak nesneyi tanımlar. Hiçbir proxy kullanılmaması gerektiğini belirtmek için özelliğini yöntemi tarafından döndürülen proxy örneğine GlobalProxySelection.GetEmptyWebProxy() ayarlayınProxy.

Yerel bilgisayar veya uygulama yapılandırma dosyası varsayılan ara sunucunun kullanıldığını belirtebilir. Proxy özelliği belirtilirse, Proxy özelliğindeki proxy ayarları yerel bilgisayarı veya uygulama yapılandırma dosyasını geçersiz kılar ve işleyici belirtilen proxy ayarlarını kullanır. Yapılandırma dosyasında proxy belirtilmemişse ve Proxy özelliği belirtilmemişse, işleyici yerel bilgisayardan devralınan proxy ayarlarını kullanır. Ara sunucu ayarı yoksa istek doğrudan sunucuya gönderilir.

sınıfı, HttpClientHandler yerel bilgisayar ayarlarından devralınan joker karakterlerle ara sunucu atlama listesini ayrıştırır. Örneğin, HttpClientHandler sınıfı tarayıcılardan atlama listesini "nt*" normal ifadesi olarak ayrıştırıyor "nt.*". Bu nedenle url'si http://nt.com sınıfını kullanarak proxy'yi atlar HttpClientHandler .

HttpClientHandler sınıfı yerel ara sunucu atlamasını destekler. Sınıfı, aşağıdaki koşullardan herhangi biri karşılanırsa hedefi yerel olarak kabul eder:

  1. Hedef düz bir ad içeriyor (URL'de nokta yok).
  2. Hedef bir geri döngü adresi (Loopback veya IPv6Loopback) içerir veya hedef yerel bilgisayara atanmış bir IPAddress adres içerir.
  3. Hedefin etki alanı soneki, yerel bilgisayarın etki alanı sonekiyle () eşleşirDomainName.

Ara sunucu yapılandırma hakkında daha fazla bilgi için bkz:

Ayrıca bkz.