Dela via


Migreringsguide för HttpWebRequest till HttpClient

Den här artikeln syftar till att vägleda utvecklare genom migreringsprocessen från HttpWebRequest, ServicePointoch ServicePointManager till HttpClient. Migreringen är nödvändig på grund av föråldringen av de äldre API:erna och de många fördelar som erbjuds av HttpClient, inklusive förbättrad prestanda, bättre resurshantering och en modernare och flexiblare API-design. Genom att följa de steg som beskrivs i det här dokumentet kommer utvecklare att kunna överföra sina kodbaser smidigt och dra full nytta av de funktioner som tillhandahålls av HttpClient.

Varning

Att migrera från HttpWebRequest, ServicePointoch ServicePointManager till HttpClient är inte bara en "trevlig att ha" prestandaförbättring. Det är viktigt att förstå att den befintliga WebRequest logikens prestanda sannolikt kommer att försämras avsevärt när du flyttar till .NET (Core). Det beror på att WebRequest underhålls som ett minimalt kompatibilitetslager, vilket innebär att det saknar många optimeringar, till exempel återanvändning av anslutningar i flera fall. Därför är övergången till HttpClient nödvändig för att säkerställa att programmets prestanda och resurshantering uppfyller moderna standarder.

Migrera från HttpWebRequest till HttpClient

Låt oss börja med några exempel:

Enkel GET-begäran med hjälp av HttpWebRequest

Här är ett exempel på hur koden kan se ut:

HttpWebRequest request = WebRequest.CreateHttp(uri);
using WebResponse response = await request.GetResponseAsync();

Enkel GET-begäran med hjälp av HttpClient

Här är ett exempel på hur koden kan se ut:

HttpClient client = new();
using HttpResponseMessage message = await client.GetAsync(uri);

Enkel POST-begäran med HttpWebRequest

Här är ett exempel på hur koden kan se ut:

HttpWebRequest request = WebRequest.CreateHttp(uri);
request.Method = "POST";
request.ContentType = "text/plain";
await using Stream stream = await request.GetRequestStreamAsync();
await stream.WriteAsync("Hello World!"u8.ToArray());
using WebResponse response = await request.GetResponseAsync();

Enkel POST-begäran med HttpClient

Här är ett exempel på hur koden kan se ut:

HttpClient client = new();
using HttpResponseMessage responseMessage = await client.PostAsync(uri, new StringContent("Hello World!"));

Migreringsguide för HttpWebRequest till HttpClient, SocketsHttpHandler

HttpWebRequest Gammalt API Nytt API Kommentar
Accept Accept Exempel: Ange begärandehuvuden.
Address RequestUri Exempel: Hämta omdirigerad URI.
AllowAutoRedirect AllowAutoRedirect Exempel: Ställa in SocketsHttpHandler-egenskaper.
AllowReadStreamBuffering Inget direkt motsvarande API Användning av buffringsegenskaper.
AllowWriteStreamBuffering Inget direkt motsvarande API Användning av buffringsegenskaper.
AuthenticationLevel Inget direkt motsvarande API Exempel: Aktivera ömsesidig autentisering.
AutomaticDecompression AutomaticDecompression Exempel: Ställa in SocketsHttpHandler-egenskaper.
CachePolicy Inget direkt motsvarande API Exempel: Använd CachePolicy-huvuden.
ClientCertificates SslOptions.ClientCertificates Användning av certifikatrelaterade egenskaper i HttpClient.
Connection Connection Exempel: Ange begärandehuvuden.
ConnectionGroupName Inget motsvarande API Ingen lösning
ContentLength ContentLength Exempel: Ange innehållsrubriker.
ContentType ContentType Exempel: Ange innehållsrubriker.
ContinueDelegate Inget motsvarande API Ingen lösning.
ContinueTimeout Expect100ContinueTimeout Exempel: Ange SocketsHttpHandler-egenskaper.
CookieContainer CookieContainer Exempel: Ange SocketsHttpHandler-egenskaper.
Credentials Credentials Exempel: Ange SocketsHttpHandler-egenskaper.
Date Date Exempel: Ange begärandehuvuden.
DefaultCachePolicy Inget direkt motsvarande API Exempel: Använd CachePolicy-huvuden.
DefaultMaximumErrorResponseLength Inget direkt motsvarande API Exempel: Ange MaximumErrorResponseLength i HttpClient.
DefaultMaximumResponseHeadersLength Inget motsvarande API MaxResponseHeadersLength kan användas i stället.
DefaultWebProxy Inget motsvarande API Proxy kan användas i stället.
Expect Expect Exempel: Ange begärandehuvuden.
HaveResponse Inget motsvarande API Underförstått genom att ha en HttpResponseMessage instans.
Headers Headers Exempel: Ange begärandehuvuden.
Host Host Exempel: Ange begärandehuvuden.
IfModifiedSince IfModifiedSince Exempel: Ange begärandehuvuden.
ImpersonationLevel Inget direkt motsvarande API Exempel: Ändra personifieringNivå.
KeepAlive Inget direkt motsvarande API Exempel: Ange begärandehuvuden.
MaximumAutomaticRedirections MaxAutomaticRedirections Exempel: Ställa in SocketsHttpHandler-egenskaper.
MaximumResponseHeadersLength MaxResponseHeadersLength Exempel: Ställa in SocketsHttpHandler-egenskaper.
MediaType Inget direkt motsvarande API Exempel: Ange innehållsrubriker.
Method Method Exempel: Användning av HttpRequestMessage-egenskaper.
Pipelined Inget motsvarande API HttpClient stöder inte pipelining.
PreAuthenticate PreAuthenticate
ProtocolVersion HttpRequestMessage.Version Exempel: Användning av HttpRequestMessage-egenskaper.
Proxy Proxy Exempel: Ställa in SocketsHttpHandler-egenskaper.
ReadWriteTimeout Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.
Referer Referrer Exempel: Ange begärandehuvuden.
RequestUri RequestUri Exempel: Användning av HttpRequestMessage-egenskaper.
SendChunked TransferEncodingChunked Exempel: Ange begärandehuvuden.
ServerCertificateValidationCallback SslOptions.RemoteCertificateValidationCallback Exempel: Ställa in SocketsHttpHandler-egenskaper.
ServicePoint Inget motsvarande API ServicePoint är inte en del av HttpClient.
SupportsCookieContainer Inget motsvarande API Detta är alltid true för HttpClient.
Timeout Timeout
TransferEncoding TransferEncoding Exempel: Ange begärandehuvuden.
UnsafeAuthenticatedConnectionSharing Inget motsvarande API Ingen lösning
UseDefaultCredentials Inget direkt motsvarande API Exempel: Ställa in SocketsHttpHandler-egenskaper.
UserAgent UserAgent Exempel: Ange begärandehuvuden.

Migrera ServicePoint(Manager)-användning

Du bör vara medveten om att det ServicePointManager är en statisk klass, vilket innebär att alla ändringar som görs i dess egenskaper kommer att ha en global effekt på alla nyligen skapade ServicePoint objekt i programmet. När du till exempel ändrar en egenskap som ConnectionLimit eller Expect100Continuepåverkar den varje ny ServicePoint-instans.

Varning

I modern .NET HttpClient tar inte hänsyn till några konfigurationer som angetts för ServicePointManager.

ServicePointManager egenskapsmappning

ServicePointManager Gammalt API Nytt API Kommentar
CheckCertificateRevocationList SslOptions.CertificateRevocationCheckMode Exempel: Aktivera CRL-kontroll med SocketsHttpHandler.
DefaultConnectionLimit MaxConnectionsPerServer Exempel: Ställa in SocketsHttpHandler-egenskaper.
DnsRefreshTimeout Inget motsvarande API Exempel: Aktivera Dns Round Robin.
EnableDnsRoundRobin Inget motsvarande API Exempel: Aktivera Dns Round Robin.
EncryptionPolicy SslOptions.EncryptionPolicy Exempel: Ställa in SocketsHttpHandler-egenskaper.
Expect100Continue ExpectContinue Exempel: Ange begärandehuvuden.
MaxServicePointIdleTime PooledConnectionIdleTimeout Exempel: Ställa in SocketsHttpHandler-egenskaper.
MaxServicePoints Inget motsvarande API ServicePoint är inte en del av HttpClient.
ReusePort Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.
SecurityProtocol SslOptions.EnabledSslProtocols Exempel: Ställa in SocketsHttpHandler-egenskaper.
ServerCertificateValidationCallback SslOptions.RemoteCertificateValidationCallback Båda är RemoteCertificateValidationCallback
UseNagleAlgorithm Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.

Varning

I modern .NET är standardvärdena för UseNagleAlgorithm egenskaperna och Expect100Continue inställda på false. Dessa värden var true som standard i .NET Framework.

ServicePointManager metodmappning

ServicePointManager Gammalt API Nytt API Kommentar
FindServicePoint Inget motsvarande API Ingen lösning
SetTcpKeepAlive Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.

ServicePoint egenskapsmappning

ServicePoint Gammalt API Nytt API Kommentar
Address HttpRequestMessage.RequestUri Det här är begärande-URI. Den här informationen finns under HttpRequestMessage.
BindIPEndPointDelegate Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.
Certificate Inget direkt motsvarande API Den här informationen kan hämtas från RemoteCertificateValidationCallback. Exempel: Hämta certifikat.
ClientCertificate Inget motsvarande API Exempel: Aktivera ömsesidig autentisering.
ConnectionLeaseTimeout SocketsHttpHandler.PooledConnectionLifetime Motsvarande inställning i HttpClient
ConnectionLimit MaxConnectionsPerServer Exempel: Ställa in SocketsHttpHandler-egenskaper.
ConnectionName Inget motsvarande API Ingen lösning
CurrentConnections Inget motsvarande API Se Nätverkstelemetri i .NET.
Expect100Continue ExpectContinue Exempel: Ange begärandehuvuden.
IdleSince Inget motsvarande API Ingen lösning
MaxIdleTime PooledConnectionIdleTimeout Exempel: Ställa in SocketsHttpHandler-egenskaper.
ProtocolVersion HttpRequestMessage.Version Exempel: Användning av HttpRequestMessage-egenskaper.
ReceiveBufferSize Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.
SupportsPipelining Inget motsvarande API HttpClient stöder inte pipelining.
UseNagleAlgorithm Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.

ServicePoint metodmappning

ServicePoint Gammalt API Nytt API Kommentar
CloseConnectionGroup Ingen motsvarighet Ingen lösning
SetTcpKeepAlive Inget direkt motsvarande API Användning av SocketsHttpHandler och ConnectCallback.

Användning av egenskaper för HttpClient och HttpRequestMessage

När du arbetar med HttpClient i .NET har du åtkomst till en mängd olika egenskaper som gör att du kan konfigurera och anpassa HTTP-begäranden och svar. Att förstå dessa egenskaper kan hjälpa dig att få ut mesta möjliga av HttpClient och se till att ditt program kommunicerar effektivt och säkert med webbtjänster.

Exempel: Användning av HttpRequestMessage-egenskaper

Här är ett exempel på hur du använder HttpClient och HttpRequestMessage tillsammans:

var client = new HttpClient();

var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com"); // Method and RequestUri usage
var request = new HttpRequestMessage() // Alternative way to set RequestUri and Method
{
    RequestUri = new Uri("https://example.com"),
    Method = HttpMethod.Post
};
request.Headers.Add("Custom-Header", "value");
request.Content = new StringContent("somestring");

using var response = await client.SendAsync(request);
var protocolVersion = response.RequestMessage.Version; // Fetch `ProtocolVersion`.

Exempel: Hämta omdirigerad URI

Här är ett exempel på hur du hämtar omdirigerad URI (samma som HttpWebRequest.Address):

var client = new HttpClient();
using var response = await client.GetAsync(uri);
var redirectedUri = response.RequestMessage.RequestUri;

Användning av SocketsHttpHandler och ConnectCallback

Med ConnectCallback egenskapen i SocketsHttpHandler kan utvecklare anpassa processen för att upprätta en TCP-anslutning. Detta kan vara användbart för scenarier där du behöver styra DNS-matchning eller använda specifika socketalternativ för anslutningen. Med hjälp ConnectCallbackav kan du fånga upp och ändra anslutningsprocessen innan den används av HttpClient.

Exempel: Binda IP-adress till socket

I den gamla metoden med kan HttpWebRequestdu ha använt anpassad logik för att binda en specifik IP-adress till en socket. Så här kan du uppnå liknande funktioner med hjälp av HttpClient och ConnectCallback:

Gammal kod med :HttpWebRequest

HttpWebRequest request = WebRequest.CreateHttp(uri);
request.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
{
    // Bind to a specific IP address
    IPAddress localAddress = IPAddress.Parse("192.168.1.100");
    return new IPEndPoint(localAddress, 0);
};
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();

Ny kod som använder HttpClient och ConnectCallback:

var handler = new SocketsHttpHandler
{
    ConnectCallback = async (context, cancellationToken) =>
    {
        // Bind to a specific IP address
        IPAddress localAddress = IPAddress.Parse("192.168.1.100");
        var socket = new Socket(localAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            socket.Bind(new IPEndPoint(localAddress, 0));
            await socket.ConnectAsync(context.DnsEndPoint, cancellationToken);
            return new NetworkStream(socket, ownsSocket: true);
        }
        catch
        {
            socket.Dispose();
            throw;
        }
    }
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);

Exempel: Använd specifika socketalternativ

Om du behöver använda specifika socketalternativ, till exempel aktivera TCP keep-alive, kan du använda ConnectCallback för att konfigurera socketen innan den används av HttpClient. I själva verket ConnectCallback är mer flexibelt för att konfigurera socketalternativ.

Gammal kod med :HttpWebRequest

ServicePointManager.ReusePort = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.ServicePoint.SetTcpKeepAlive(true, 60000, 1000);
request.ServicePoint.ReceiveBufferSize = 8192;
request.ServicePoint.UseNagleAlgorithm = false;
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();

Ny kod som använder HttpClient och ConnectCallback:

var handler = new SocketsHttpHandler
{
    ConnectCallback = async (context, cancellationToken) =>
    {
        var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
        try
        {
            // Setting TCP Keep Alive
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 60);
            socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 1);

            // Setting ReceiveBufferSize
            socket.ReceiveBufferSize = 8192;

            // Enabling ReusePort
            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);

            // Disabling Nagle Algorithm
            socket.NoDelay = true;

            await socket.ConnectAsync(context.DnsEndPoint, cancellationToken);
            return new NetworkStream(socket, ownsSocket: true);
        }
        catch
        {
            socket.Dispose();
            throw;
        }
    }
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);

Exempel: Aktivera DNS-resursallokering

DNS Round Robin är en teknik som används för att distribuera nätverkstrafik över flera servrar genom att rotera genom en lista över IP-adresser som är associerade med ett enda domännamn. Detta bidrar till belastningsutjämning och förbättrad tillgänglighet för tjänster. När du använder HttpClient kan du implementera DNS Round Robin genom att manuellt hantera DNS-matchningen och rotera genom IP-adresserna med egenskapen ConnectCallback för SocketsHttpHandler.

Om du vill aktivera DNS Round Robin med HttpClient kan du använda egenskapen ConnectCallback för att manuellt matcha DNS-posterna och rotera genom IP-adresserna. Här är ett exempel för HttpWebRequest och HttpClient:

Gammal kod med :HttpWebRequest

ServicePointManager.DnsRefreshTimeout = 60000;
ServicePointManager.EnableDnsRoundRobin = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();

I det äldre HttpWebRequest API:et var det enkelt att aktivera DNS Round Robin på grund av dess inbyggda stöd för den här funktionen. Det nyare HttpClient API:et tillhandahåller dock inte samma inbyggda funktioner. Trots detta kan du uppnå liknande beteende genom att implementera en DnsRoundRobinConnector som manuellt roterar genom DE IP-adresser som returneras av DNS-matchning.

Ny kod med :HttpClient

// This is available as NuGet Package: https://www.nuget.org/packages/DnsRoundRobin/
// The original source code can be found also here: https://github.com/MihaZupan/DnsRoundRobin
public sealed class DnsRoundRobinConnector : IDisposable

Du hittar implementeringen av DnsRoundRobinConnector här.

DnsRoundRobinConnector Användning:

private static readonly DnsRoundRobinConnector s_roundRobinConnector = new(
        dnsRefreshInterval: TimeSpan.FromSeconds(10),
        endpointConnectTimeout: TimeSpan.FromSeconds(5));
static async Task DnsRoundRobinConnectAsync()
{
    var handler = new SocketsHttpHandler
    {
        ConnectCallback = async (context, cancellation) =>
        {
            Socket socket = await DnsRoundRobinConnector.Shared.ConnectAsync(context.DnsEndPoint, cancellation);
            // Or you can create and use your custom DnsRoundRobinConnector instance
            // Socket socket = await s_roundRobinConnector.ConnectAsync(context.DnsEndPoint, cancellation);
            return new NetworkStream(socket, ownsSocket: true);
        }
    };
    var client = new HttpClient(handler);
    HttpResponseMessage response = await client.GetAsync(Uri);
}

Exempel: Ange egenskaper för SocketsHttpHandler

SocketsHttpHandler är en kraftfull och flexibel hanterare i .NET som tillhandahåller avancerade konfigurationsalternativ för hantering av HTTP-anslutningar. Genom att ange olika egenskaper för SocketsHttpHandler kan du finjustera HTTP-klientens beteende för att uppfylla specifika krav, till exempel prestandaoptimering, säkerhetsförbättringar och anpassad anslutningshantering.

Här är ett exempel på hur du konfigurerar SocketsHttpHandler med olika egenskaper och använder det med HttpClient:

var cookieContainer = new CookieContainer();
cookieContainer.Add(new Cookie("cookieName", "cookieValue"));

var handler = new SocketsHttpHandler
{
    AllowAutoRedirect = true,
    AutomaticDecompression = DecompressionMethods.All,
    Expect100ContinueTimeout = TimeSpan.FromSeconds(1),
    CookieContainer = cookieContainer,
    Credentials = new NetworkCredential("user", "pass"),
    MaxAutomaticRedirections = 10,
    MaxResponseHeadersLength = 1,
    Proxy = new WebProxy("http://proxyserver:8080"), // Don't forget to set UseProxy
    UseProxy = true,
};

var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);

Exempel: Ändra personifieringNivå

Den här funktionen är specifik för vissa plattformar och är något inaktuell. Om du behöver en lösning kan du läsa det här avsnittet i koden.

När du arbetar med HttpClientkan du behöva hantera klientcertifikat i olika syften, till exempel anpassad validering av servercertifikat eller hämtning av servercertifikatet. HttpClient innehåller flera egenskaper och alternativ för att hantera certifikat effektivt.

Exempel: Kontrollera listan över återkallade certifikat med SocketsHttpHandler

Med CheckCertificateRevocationList egenskapen i SocketsHttpHandler.SslOptions kan utvecklare aktivera eller inaktivera kontrollen av listor över återkallade certifikat (CRL) under handskakning av SSL/TLS. Om du aktiverar den här egenskapen ser du till att klienten verifierar om serverns certifikat har återkallats, vilket förbättrar säkerheten för anslutningen.

Gammal kod med :HttpWebRequest

ServicePointManager.CheckCertificateRevocationList = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();

Ny kod med :HttpClient

bool checkCertificateRevocationList = true;
var handler = new SocketsHttpHandler
{
    SslOptions =
    {
        CertificateRevocationCheckMode = checkCertificateRevocationList ? X509RevocationMode.Online : X509RevocationMode.NoCheck,
    }
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);

Exempel: Hämta certifikat

Om du vill hämta certifikatet RemoteCertificateValidationCallback från i HttpClientkan du använda ServerCertificateCustomValidationCallback egenskapen HttpClientHandler eller SocketsHttpHandler.SslOptions. Med det här återanropet kan du inspektera serverns certifikat under handskakningen SSL/TLS.

Gammal kod med :HttpWebRequest

HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
X509Certificate? serverCertificate = request.ServicePoint.Certificate;

Ny kod med :HttpClient

X509Certificate? serverCertificate = null;
var handler = new SocketsHttpHandler
{
    SslOptions = new SslClientAuthenticationOptions
    {
        RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
        {
            serverCertificate = certificate;

            // Leave the validation as-is.
            return sslPolicyErrors == SslPolicyErrors.None;
        }
    }
};
var client = new HttpClient(handler);
using var response = await client.GetAsync("https://example.com");

Exempel: Aktivera ömsesidig autentisering

Ömsesidig autentisering, även kallat dubbelriktad SSL- eller klientcertifikatautentisering, är en säkerhetsprocess där både klienten och servern autentiserar varandra. Detta säkerställer att båda parter är de som de påstår sig vara, vilket ger ytterligare ett säkerhetslager för känslig kommunikation. I HttpClientkan du aktivera ömsesidig autentisering genom att HttpClientHandler konfigurera eller SocketsHttpHandler inkludera klientcertifikatet och verifiera serverns certifikat.

Följ dessa steg för att aktivera ömsesidig autentisering:

  • Läs in klientcertifikatet.
  • Konfigurera HttpClientHandler eller SocketsHttpHandler så att det innehåller klientcertifikatet.
  • Konfigurera servercertifikatets valideringsåteranrop om anpassad validering behövs.

Här är ett exempel med SocketsHttpHandler:

var handler = new SocketsHttpHandler
{
    SslOptions = new SslClientAuthenticationOptions
    {
        ClientCertificates = new X509CertificateCollection
        {
            // Load the client certificate from a file
            new X509Certificate2("path_to_certificate.pfx", "certificate_password")
        },
        RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
        {
            // Custom validation logic for the server certificate
            return sslPolicyErrors == SslPolicyErrors.None;
        }
    }
};

var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);

Användning av rubrikegenskaper

Rubriker spelar en avgörande roll i HTTP-kommunikation och tillhandahåller viktiga metadata om begäran och svar. När du arbetar med HttpClient i .NET kan du ange och hantera olika rubrikegenskaper för att styra beteendet för dina HTTP-begäranden och svar. Genom att förstå hur du använder dessa rubrikegenskaper effektivt kan du se till att ditt program kommunicerar effektivt och säkert med webbtjänster.

Ange begärandehuvuden

Begärandehuvuden används för att ge ytterligare information till servern om den begäran som görs. Vanliga användningsfall är att ange innehållstyp, ange autentiseringstoken och lägga till anpassade rubriker. Du kan ange begärandehuvuden DefaultRequestHeaders med egenskapen HttpClient eller egenskapen Headers för HttpRequestMessage.

Exempel: Ange anpassade begärandehuvuden

Ange standardrubriker för anpassade begäranden i HttpClient

var client = new HttpClient();
client.DefaultRequestHeaders.Add("Custom-Header", "value");

Ange anpassade begärandehuvuden i HttpRequestMessage

var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Add("Custom-Header", "value");

Exempel: Ange vanliga begärandehuvuden

När du arbetar med HttpRequestMessage i .NET är det viktigt att ange vanliga begärandehuvuden för att ge ytterligare information till servern om den begäran som görs. Dessa rubriker kan innehålla autentiseringstoken med mera. Korrekt konfiguration av dessa huvuden säkerställer att dina HTTP-begäranden bearbetas korrekt av servern. En omfattande lista över vanliga egenskaper som är tillgängliga i finns i HttpRequestHeadersEgenskaper.

Om du vill ange vanliga begärandehuvuden Headers i HttpRequestMessagekan du använda -egenskapen för HttpRequestMessage objektet. Den här egenskapen ger åtkomst till HttpRequestHeaders samlingen, där du kan lägga till eller ändra rubriker efter behov.

Ange vanliga standardrubriker för begäranden i HttpClient

using System.Net.Http.Headers;

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "token");

Ange vanliga begärandehuvuden i HttpRequestMessage

using System.Net.Http.Headers;

var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "token");

Exempel: Ange innehållsrubriker

Innehållshuvuden används för att ge ytterligare information om brödtexten i en HTTP-begäran eller ett HTTP-svar. När du arbetar med HttpClient i .NET kan du ange innehållshuvuden för att ange medietyp, kodning och andra metadata som är relaterade till innehållet som skickas eller tas emot. Korrekt konfiguration av innehållshuvuden säkerställer att servern och klienten kan tolka och bearbeta innehållet korrekt.

var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, uri);

// Create the content and set the content headers
var jsonData = "{\"key\":\"value\"}";
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");

// The following headers are set automatically by `StringContent`. If you wish to override their values, you can do it like so:
// content.Headers.ContentType = new MediaTypeHeaderValue("application/json; charset=utf-8");
// content.Headers.ContentLength = Encoding.UTF8.GetByteCount(jsonData);

// Assign the content to the request
request.Content = content;

using var response = await client.SendAsync(request);

Exempel: Ange MaximumErrorResponseLength i HttpClient

Med MaximumErrorResponseLength användningen kan utvecklare ange den maximala längden på det felsvarsinnehåll som hanteraren buffrar. Detta är användbart för att kontrollera mängden data som läss och lagras i minnet när ett felsvar tas emot från servern. Med den här tekniken kan du förhindra överdriven minnesanvändning och förbättra programmets prestanda vid hantering av stora felsvar.

Det finns några sätt att göra det på, vi undersöker TruncatedReadStream tekniken i det här exemplet:

internal sealed class TruncatedReadStream(Stream innerStream, long maxSize) : Stream
{
    private long _maxRemainingLength = maxSize;
    public override bool CanRead => true;
    public override bool CanSeek => false;
    public override bool CanWrite => false;

    public override long Length => throw new NotSupportedException();
    public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }

    public override void Flush() => throw new NotSupportedException();

    public override int Read(byte[] buffer, int offset, int count)
    {
        return Read(new Span<byte>(buffer, offset, count));
    }

    public override int Read(Span<byte> buffer)
    {
        int readBytes = innerStream.Read(buffer.Slice(0, (int)Math.Min(buffer.Length, _maxRemainingLength)));
        _maxRemainingLength -= readBytes;
        return readBytes;
    }

    public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        return ReadAsync(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask();
    }

    public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
    {
        int readBytes = await innerStream.ReadAsync(buffer.Slice(0, (int)Math.Min(buffer.Length, _maxRemainingLength)), cancellationToken)
            .ConfigureAwait(false);
        _maxRemainingLength -= readBytes;
        return readBytes;
    }

    public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();

    public override ValueTask DisposeAsync() => innerStream.DisposeAsync();

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            innerStream.Dispose();
        }
    }
}

Och användningsexempel på TruncatedReadStream:

int maxErrorResponseLength = 1 * 1024; // 1 KB

HttpClient client = new HttpClient();
using HttpResponseMessage response = await client.GetAsync(Uri);

if (response.Content is not null)
{
    Stream responseReadStream = await response.Content.ReadAsStreamAsync();
    // If MaxErrorResponseLength is set and the response status code is an error code, then wrap the response stream in a TruncatedReadStream
    if (maxErrorResponseLength >= 0 && !response.IsSuccessStatusCode)
    {
        responseReadStream = new TruncatedReadStream(responseReadStream, maxErrorResponseLength);
    }
    // Read the response stream
    Memory<byte> buffer = new byte[1024];
    int readValue = await responseReadStream.ReadAsync(buffer);
}

Exempel: Använd CachePolicy-huvuden

Varning

HttpClient har inte inbyggd logik för att cachelagrar svar. Det finns ingen annan lösning än att implementera all cachelagring själv. Det går inte att cachelagra genom att ange rubrikerna.

När du migrerar från HttpWebRequest till HttpClientär det viktigt att hantera cacherelaterade rubriker som pragma och cache-control. Dessa rubriker styr hur svar cachelagras och hämtas, vilket säkerställer att ditt program fungerar som förväntat när det gäller prestanda och datas färskhet.

I HttpWebRequestkan du ha använt CachePolicy egenskapen för att ange dessa rubriker. I måste du dock HttpClientange dessa rubriker manuellt på begäran.

Gammal kod med :HttpWebRequest

HttpWebRequest request = WebRequest.CreateHttp(uri);
request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();

I det äldre HttpWebRequest API:et var det enkelt att tillämpa CachePolicy på grund av dess inbyggda stöd för den här funktionen. Det nyare HttpClient API:et tillhandahåller dock inte samma inbyggda funktioner. Trots detta kan du uppnå liknande beteende genom att implementera en AddCacheControlHeaders som manuellt lägger till cacherelaterade huvuden.

Ny kod med :HttpClient

public static class CachePolicy
{
    public static void AddCacheControlHeaders(HttpRequestMessage request, RequestCachePolicy policy)

Du hittar implementeringen av AddCacheControlHeaders här.

AddCacheControlHeaders Användning:

static async Task AddCacheControlHeaders()
{
    HttpClient client = new HttpClient();
    HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, Uri);
    CachePolicy.AddCacheControlHeaders(requestMessage, new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore));
    HttpResponseMessage response = await client.SendAsync(requestMessage);
}

Användning av buffringsegenskaper

När du migrerar från HttpWebRequest till HttpClientär det viktigt att förstå skillnaderna i hur dessa två API:er hanterar buffring.

Gammal kod med :HttpWebRequest

I HttpWebRequesthar du direkt kontroll över buffringsegenskaper via AllowWriteStreamBuffering egenskaperna och AllowReadStreamBuffering . Dessa egenskaper aktiverar eller inaktiverar buffring av data som skickas till och tas emot från servern.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AllowReadStreamBuffering = true; // Default is `false`.
request.AllowWriteStreamBuffering = false; // Default is `true`.

Ny kod med :HttpClient

I HttpClientfinns det inga direkta motsvarigheter till AllowWriteStreamBuffering egenskaperna och AllowReadStreamBuffering .

HttpClient buffrar inte begärandeorgan på egen hand, utan delegerar i stället ansvaret till de HttpContent använda. Innehåll som StringContent eller ByteArrayContent är logiskt redan buffrade i minnet, medan användning StreamContent inte medför någon buffring som standard. Om du vill framtvinga att innehållet buffrats kan du anropa HttpContent.LoadIntoBufferAsync innan du skickar begäran. Här är ett exempel:

HttpClient client = new HttpClient();

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StreamContent(yourStream);
await request.Content.LoadIntoBufferAsync();

HttpResponseMessage response = await client.SendAsync(request);

I HttpClient läsbuffertning är aktiverat som standard. För att undvika det kan du ange HttpCompletionOption.ResponseHeadersRead flaggan eller använda hjälpen GetStreamAsync .

HttpClient client = new HttpClient();

using HttpResponseMessage response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
await using Stream responseStream = await response.Content.ReadAsStreamAsync();

// Or simply
await using Stream responseStream = await client.GetStreamAsync(uri);