Classe System.Net.Http.HttpClient

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

L'istanza della HttpClient classe funge da sessione per inviare richieste HTTP. Un'istanza HttpClient è una raccolta di impostazioni applicate a tutte le richieste eseguite da tale istanza. Inoltre, ogni HttpClient istanza usa il proprio pool di connessioni, isolando le richieste dalle richieste eseguite da altre HttpClient istanze.

Creazione di istanze

HttpClient deve essere creata un'istanza una sola volta e riutilizzata per tutta la durata di un'applicazione. In .NET Core e .NET 5+, le connessioni HttpClient all'interno dell'istanza del gestore e riutilizzano una connessione tra più richieste. Se si crea un'istanza di una classe HttpClient per ogni richiesta, il numero di socket disponibili in carichi elevati verrà esaurito. Questa esaurimento genererà SocketException errori.

È possibile configurare opzioni aggiuntive passando un "gestore", ad esempio HttpClientHandler (o SocketsHttpHandler in .NET Core 2.1 o versione successiva), come parte del costruttore. Le proprietà di connessione nel gestore non possono essere modificate dopo l'invio di una richiesta, quindi un motivo per creare una nuova istanza HttpClient sarebbe se fosse necessario modificare le proprietà di connessione. Se richieste diverse richiedono impostazioni diverse, questo può comportare anche la presenza di più HttpClient istanze di un'applicazione, in cui ogni istanza è configurata in modo appropriato e quindi le richieste vengono inviate nel client pertinente.

HttpClient risolve solo le voci DNS quando viene creata una connessione. Non tiene traccia delle durate (TTL) specificate dal server DNS. Se le voci DNS cambiano regolarmente, che possono verificarsi in alcuni scenari di contenitore, il client non rispetterà tali aggiornamenti. Per risolvere questo problema, è possibile limitare la durata della connessione impostando la SocketsHttpHandler.PooledConnectionLifetime proprietà , in modo che la ricerca DNS sia necessaria quando la connessione viene sostituita.

public class GoodController : ApiController
{
    private static readonly HttpClient httpClient;

    static GoodController()
    {
        var socketsHandler = new SocketsHttpHandler
        {
            PooledConnectionLifetime = TimeSpan.FromMinutes(2)
        };

        httpClient = new HttpClient(socketsHandler);
    }
}

In alternativa alla creazione di una sola istanza HttpClient, è anche possibile usare IHttpClientFactory per gestire le istanze HttpClient. Per ricevere ulteriori informazioni, consultare l'articolo Linee guida per l'uso di HttpClient.

Derivazione

Funge HttpClient anche da classe di base per client HTTP più specifici. Un esempio è un FacebookHttpClient che fornisce metodi aggiuntivi specifici di un servizio Web Facebook (ad esempio, un GetFriends metodo). Le classi derivate non devono eseguire l'override dei metodi virtuali nella classe . Usare invece un overload del costruttore che accetta HttpMessageHandler per configurare qualsiasi elaborazione pre-richiesta o post-richiesta.

Trasporti

è un'API HttpClient di alto livello che esegue il wrapping delle funzionalità di livello inferiore disponibili in ogni piattaforma in cui viene eseguita.

In ogni piattaforma tenta HttpClient di usare il trasporto migliore disponibile:

Host/Runtime Backend
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Windows nativo WinHttpHandler (compatibile con HTTP 2.0)
Windows/.NET Core 1.0-2.0 Windows nativo WinHttpHandler (compatibile con HTTP 2.0)
Android/Xamarin Selezionato in fase di compilazione. Può usare HttpWebRequest o essere configurato per l'uso nativo di Android HttpURLConnection
iOS, tvOS, watchOS/Xamarin Selezionato in fase di compilazione. Può usare HttpWebRequest o essere configurato per l'uso di NSUrlSession Apple (con supporto HTTP 2.0)
macOS/Xamarin Selezionato in fase di compilazione. Può usare HttpWebRequest o essere configurato per l'uso di NSUrlSession Apple (con supporto HTTP 2.0)
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurlTrasporto HTTP basato su http (con supporto http 2.0)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurlTrasporto HTTP basato su http (con supporto http 2.0)
.NET Core 2.1 e versioni successive System.Net.Http.SocketsHttpHandler

Gli utenti possono anche configurare un trasporto specifico per HttpClient richiamando il HttpClient costruttore che accetta un oggetto HttpMessageHandler.

.NET Framework & Mono

Per impostazione predefinita, in .NET Framework e Mono viene HttpWebRequest usato per inviare richieste al server. Questo comportamento può essere modificato specificando un gestore diverso in uno degli overload del costruttore con un HttpMessageHandler parametro . Se sono necessarie funzionalità come l'autenticazione o la memorizzazione nella cache, è possibile usare WebRequestHandler per configurare le impostazioni e l'istanza può essere passata al costruttore. Il gestore restituito può essere passato a un overload del costruttore con un HttpMessageHandler parametro .

.NET Core

A partire da .NET Core 2.1, la System.Net.Http.SocketsHttpHandler classe anziché fornisce l'implementazione usata da classi di HttpClientHandler rete HTTP di livello superiore, ad HttpClientesempio . L'uso di SocketsHttpHandler offre numerosi vantaggi:

  • Miglioramento significativo delle prestazioni rispetto all'implementazione precedente.
  • Eliminazione delle dipendenze della piattaforma, che semplifica la distribuzione e la manutenzione. Ad esempio, libcurl non è più una dipendenza da .NET Core per macOS e .NET Core per Linux.
  • Comportamento coerente in tutte le piattaforme .NET.

Se questa modifica è indesiderata, in Windows è possibile continuare a usare WinHttpHandler facendo riferimento al pacchetto NuGet e passandolo manualmente al costruttore di HttpClient.

Configurare il comportamento usando le opzioni di configurazione di runtime

Alcuni aspetti del HttpClientcomportamento sono personalizzabili tramite le opzioni di configurazione di runtime. Tuttavia, il comportamento di queste opzioni è diverso rispetto alle versioni di .NET. Ad esempio, in .NET Core 2.1 - 3.1 è possibile configurare se SocketsHttpHandler viene usato per impostazione predefinita, ma tale opzione non è più disponibile a partire da .NET 5.

Pool di connessioni

HttpClient pool di connessioni HTTP laddove possibile e le usa per più di una richiesta. Ciò può avere un vantaggio significativo in termini di prestazioni, soprattutto per le richieste HTTPS, perché l'handshake di connessione viene eseguito una sola volta.

Connessione proprietà del pool di Connessione possono essere configurate in un HttpClientHandler oggetto o SocketsHttpHandler passate durante la costruzione, tra cui MaxConnectionsPerServer, PooledConnectionIdleTimeoute PooledConnectionLifetime.

L'eliminazione dell'istanza HttpClient chiude le connessioni aperte e annulla le richieste in sospeso.

Nota

Se si inviano simultaneamente richieste HTTP/1.1 allo stesso server, è possibile creare nuove connessioni. Anche se si riutilizza l'istanza HttpClient , se la frequenza delle richieste è elevata o se sono presenti limitazioni del firewall, è possibile esaurire i socket disponibili a causa dei timer di pulizia TCP predefiniti. Per limitare il numero di connessioni simultanee, è possibile impostare la MaxConnectionsPerServer proprietà . Per impostazione predefinita, il numero di connessioni HTTP/1.1 simultanee è illimitato.

Memorizzazione nel buffer e durata delle richieste

Per impostazione predefinita, i metodi HttpClient (ad eccezione GetStreamAsyncdi ) memorizzano nel buffer le risposte dal server, leggendo tutto il corpo della risposta in memoria prima di restituire il risultato asincrono. Tali richieste continueranno fino a quando non si verifica una delle seguenti operazioni:

È possibile modificare il comportamento di buffering in base alle richieste usando il HttpCompletionOption parametro disponibile in alcuni overload del metodo. Questo argomento può essere usato per specificare se deve Task<TResult> essere considerato completo dopo aver letto solo le intestazioni della risposta o dopo aver letto e memorizzato nel buffer il contenuto della risposta.

Se l'app che usa HttpClient e classi correlate nello System.Net.Http spazio dei nomi intende scaricare grandi quantità di dati (50 megabyte o più), l'app deve trasmettere tali download e non usare il buffer predefinito. Se si usa il buffering predefinito, l'utilizzo della memoria client avrà dimensioni molto elevate, con conseguente riduzione sostanziale delle prestazioni.

Thread safety

I metodi seguenti sono thread-safe:

Proxy

Per impostazione predefinita, HttpClient legge la configurazione proxy dalle variabili di ambiente o dalle impostazioni utente/sistema, a seconda della piattaforma. È possibile modificare questo comportamento passando un WebProxy oggetto o IWebProxy a, in ordine di precedenza:

  • Proprietà Proxy in un HttpClientHandler passato durante la costruzione di HttpClient
  • La DefaultProxy proprietà statica (influisce su tutte le istanze)

È possibile disabilitare il proxy usando UseProxy. La configurazione predefinita per gli utenti di Windows consiste nel provare a rilevare un proxy usando l'individuazione di rete, che può essere lento. Per le applicazioni a velocità effettiva elevata in cui è noto che un proxy non è necessario, è consigliabile disabilitare il proxy.

Le impostazioni proxy (ad esempio Credentials) devono essere modificate solo prima che venga effettuata la prima richiesta usando HttpClient. Le modifiche apportate dopo l'uso di HttpClient per la prima volta potrebbero non essere riflesse nelle richieste successive.

Timeout

È possibile usare Timeout per impostare un timeout predefinito per tutte le richieste HTTP dall'istanza HttpClient. Il timeout si applica solo ai metodi xxxAsync che causano l'avvio di una richiesta/risposta. Se viene raggiunto il timeout, l'oggetto Task<TResult> per la richiesta viene annullato.

È possibile impostare alcuni timeout aggiuntivi se si passa un'istanza SocketsHttpHandler quando si costruisce l'oggetto HttpClient:

Proprietà Descrizione
ConnectTimeout Specifica un timeout utilizzato quando una richiesta richiede la creazione di una nuova connessione TCP. Se si verifica il timeout, la richiesta Task<TResult> viene annullata.
PooledConnectionLifetime Specifica un timeout da utilizzare per ogni connessione nel pool di connessioni. Se la connessione è inattiva, la connessione viene chiusa immediatamente; in caso contrario, la connessione viene chiusa alla fine della richiesta corrente.
PooledConnectionIdleTimeout Se una connessione nel pool di connessioni è inattiva per questo lungo periodo, la connessione viene chiusa.
Expect100ContinueTimeout Se la richiesta ha un'intestazione "Expect: 100-continue", ritarda l'invio del contenuto fino al timeout o fino alla ricezione di una risposta "100-continue".

HttpClient risolve solo le voci DNS quando vengono create le connessioni. Non tiene traccia delle durate (TTL) specificate dal server DNS. Se le voci DNS cambiano regolarmente, che possono verificarsi in alcuni scenari di contenitore, è possibile usare PooledConnectionLifetime per limitare la durata della connessione in modo che la ricerca DNS sia necessaria quando si sostituisce la connessione.