HTTP-Client in C#: Anfragen richtig stellen — Fortgeschrittenenniveau
In der modernen .NET-Entwicklung geht die Arbeit mit HTTP-Anfragen weit über den einfachen Aufruf von WebClient oder dem grundlegenden HttpClient hinaus. Auf fortgeschrittenem Niveau müssen die Verwaltung des Verbindungspools, die korrekte Fehlerbehandlung, Timeouts, Wiederholungsrichtlinien und die asynchrone Ausführung berücksichtigt werden. In diesem Artikel behandeln wir die Best Practices für die Arbeit mit dem HTTP-Client in C#, die Ihnen helfen, zuverlässige und leistungsstarke Anwendungen zu erstellen.
1. Korrekte Arbeit mit HttpClient und dem Verbindungspool
Einer der häufigsten Fehler ist die Erstellung einer neuen Instanz von HttpClient für jede Anfrage. Dies führt zur Socket-Erschöpfung (Socket Exhaustion), da jede Instanz eine offene TCP-Verbindung im Zustand TIME_WAIT hält.
Falsch:
public async Task<string> GetDataAsync(string url){ using (var client = new HttpClient()) { return await client.GetStringAsync(url); }}Richtig: Verwenden Sie eine einzelne statische oder Singleton-Instanz von HttpClient.
public class HttpService{ private static readonly HttpClient _client = new HttpClient();
public async Task<string> GetDataAsync(string url) { return await _client.GetStringAsync(url); }}Für eine feinere Kontrolle verwenden Sie IHttpClientFactory aus dem Paket Microsoft.Extensions.Http. Die Factory verwaltet den Pool und stellt Verbindungen bei DNS-Ausfällen automatisch wieder her.
// In Startup.cs oder Program.csservices.AddHttpClient("MyClient", client =>{ client.BaseAddress = new Uri("https://api.example.com"); client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");});
// Im Servicepublic class MyService{ private readonly IHttpClientFactory _httpClientFactory;
public MyService(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; }
public async Task<string> GetDataAsync() { var client = _httpClientFactory.CreateClient("MyClient"); return await client.GetStringAsync("/data"); }}2. Timeouts und Abbruch von Anfragen
Ohne Timeouts kann Ihr Client auf unbestimmte Zeit hängen bleiben. In HttpClient gibt es zwei Mechanismen:
- Timeout — ein allgemeines Timeout für die gesamte Anfrage.
- CancellationToken — zum externen Abbrechen der Anfrage (z. B. wenn der Benutzer die Anwendung schließt).
Setzen Sie Timeout sinnvoll. Für die meisten APIs sind 10–30 Sekunden angemessen.
var client = new HttpClient{ Timeout = TimeSpan.FromSeconds(15)};
// Beispiel mit CancellationTokenSourceusing var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));try{ var response = await client.GetAsync("https://slow-api.example.com", cts.Token);}catch (TaskCanceledException){ Console.WriteLine("Anfrage aufgrund von Timeout abgebrochen.");}Wichtig: Timeout und CancellationToken arbeiten zusammen. Wenn das CancellationToken früher ausgelöst wird, wird die Anfrage schneller abgebrochen.
3. Fehlerbehandlung und Wiederholungsrichtlinie (Retry)
Netzwerkausfälle und temporäre Serverfehler sind an der Tagesordnung. Anstatt sofort abzubrechen, implementieren Sie eine Wiederholungsrichtlinie mit exponentiellem Backoff. Hierfür eignet sich die Bibliothek Polly hervorragend.
using Polly;using Polly.Extensions.Http;
// Definieren der Wiederholungsrichtlinievar retryPolicy = HttpPolicyExtensions .HandleTransientHttpError() // 5xx, 408 .Or<HttpRequestException>() .WaitAndRetryAsync(3, retryAttempt => Tim