Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieser Artikel führt Entwickler durch den Prozess der Migration von HttpWebRequest, ServicePoint und ServicePointManager zu HttpClient. Die Migration ist aufgrund der Obsoleszenz der älteren APIs und der zahlreichen Vorteile erforderlich, die durch HttpClientverbesserte Leistung, bessere Ressourcenverwaltung und ein moderneres und flexibleres API-Design geboten werden. Wenn Entwickler die in diesem Dokument beschriebenen Schritte befolgen, können sie ihre Codebasen reibungslos umstellen und die von HttpClient bereitgestellten Features vollständig nutzen.
Warnung
Die Migration von HttpWebRequest, ServicePoint und ServicePointManager zu HttpClient ist nicht nur eine "schön zu haben" Leistungsverbesserung. Ihnen muss klar sein, dass die Leistung der vorhandenen WebRequest Logik wahrscheinlich erheblich sinkt, sobald Sie zu .NET (Core) wechseln. Das liegt daran, dass WebRequest als minimale Kompatibilitätsschicht beibehalten wird, was bedeutet, dass viele Optimierungen fehlen, z. B. die Wiederverwendung von Verbindungen in zahlreichen Fällen. Daher ist der Übergang zu HttpClient ist eine wichtige Voraussetzung, um sicherzustellen, dass die Leistung und das Ressourcenmanagement Ihrer Anwendung den modernen Standards entsprechen.
Migrieren von HttpWebRequest zu HttpClient
Beginnen wir mit einigen Beispielen:
Einfache GET-Anforderung mithilfe von HttpWebRequest
Hier ist ein Beispiel dafür, wie der Code aussehen könnte:
HttpWebRequest request = WebRequest.CreateHttp(uri);
using WebResponse response = await request.GetResponseAsync();
Einfache GET-Anforderung mithilfe von HttpClient
Hier ist ein Beispiel dafür, wie der Code aussehen könnte:
HttpClient client = new();
using HttpResponseMessage message = await client.GetAsync(uri);
Einfache POST-Anforderung mithilfe von HttpWebRequest
Hier ist ein Beispiel dafür, wie der Code aussehen könnte:
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();
Einfache POST-Anforderung mithilfe von HttpClient
Hier ist ein Beispiel dafür, wie der Code aussehen könnte:
HttpClient client = new();
using HttpResponseMessage responseMessage = await client.PostAsync(uri, new StringContent("Hello World!"));
HttpWebRequest zu HttpClient: SocketsHttpHandler-Migrationshandbuch
Migrieren der ServicePointManager Nutzung
Sie sollten sich bewusst sein, dass ServicePointManager eine statische Klasse ist. Das bedeutet, dass alle Änderungen, die an ihren Eigenschaften vorgenommen wurden, global Auswirkungen auf alle neu erstellten ServicePoint-Objekte innerhalb der Anwendung haben. Wenn Sie beispielsweise eine Eigenschaft wie ConnectionLimit oder Expect100Continue ändern, wirkt sich dies auf jede neue ServicePoint-Instanz aus.
Warnung
In modernem .NET werden keine Konfigurationen berücksichtigt, HttpClient die auf ServicePointManager.
Zuordnung von ServicePointManager-Eigenschaften
Warnung
In modernem .NET sind die Standardwerte für die UseNagleAlgorithm- und Expect100Continue-Eigenschaften auf festgelegt false. Diese Werte waren true standardmäßig in .NET Framework.
Zuordnung von ServicePointManager-Methoden
| ServicePointManagerAlte API | Neue API | Hinweise |
|---|---|---|
FindServicePoint |
Keine entsprechende API | Keine Problemumgehung |
SetTcpKeepAlive |
Keine direkte entsprechende API | Verwendung von SocketsHttpHandler und ConnectCallback. |
Zuordnung von ServicePoint-Eigenschaften
| ServicePointAlte API | Neue API | Hinweise |
|---|---|---|
Address |
HttpRequestMessage.RequestUri |
Dies ist anforderungs-URI, diese Informationen finden Sie unter HttpRequestMessage. |
BindIPEndPointDelegate |
Keine direkte entsprechende API | Verwendung von SocketsHttpHandler und ConnectCallback. |
Certificate |
Keine direkte entsprechende API | Diese Informationen können abgerufen werden von RemoteCertificateValidationCallback.
Beispiel: Abrufen des Zertifikats. |
ClientCertificate |
Keine entsprechende API | Beispiel: Aktivieren der gegenseitigen Authentifizierung. |
ConnectionLeaseTimeout |
SocketsHttpHandler.PooledConnectionLifetime |
Entsprechende Einstellung in HttpClient |
ConnectionLimit |
MaxConnectionsPerServer | Beispiel: Festlegen von SocketsHttpHandler-Eigenschaften. |
ConnectionName |
Keine entsprechende API | Keine Problemumgehung |
CurrentConnections |
Keine entsprechende API | Siehe Netzwerktelemetrie in .NET |
Expect100Continue |
ExpectContinue | Beispiel: Festlegen von Anforderungsheadern. |
IdleSince |
Keine entsprechende API | Keine Problemumgehung |
MaxIdleTime |
PooledConnectionIdleTimeout | Beispiel: Festlegen von SocketsHttpHandler-Eigenschaften. |
ProtocolVersion |
HttpRequestMessage.Version |
Beispiel: Verwendung von HttpRequestMessage-Eigenschaften. |
ReceiveBufferSize |
Keine direkte entsprechende API | Verwendung von SocketsHttpHandler und ConnectCallback. |
SupportsPipelining |
Keine entsprechende API |
HttpClient unterstützt keine Pipelining. |
UseNagleAlgorithm |
Keine direkte entsprechende API | Verwendung von SocketsHttpHandler und ConnectCallback. |
Zuordnung von ServicePoint-Methoden
| ServicePointAlte API | Neue API | Hinweise |
|---|---|---|
CloseConnectionGroup |
Keine Entsprechung | Keine Problemumgehung |
SetTcpKeepAlive |
Keine direkte entsprechende API | Verwendung von SocketsHttpHandler und ConnectCallback. |
Verwendung von HttpClient und HttpRequestMessage Eigenschaften
Beim Arbeiten mit HttpClient in .NET haben Sie Zugriff auf eine Vielzahl von Eigenschaften, mit denen Sie HTTP-Anforderungen und -Antworten konfigurieren und anpassen können. Indem Sie diese Eigenschaften verstehen, können Sie HttpClient optimal nutzen und sicherstellen, dass Ihre Anwendung effizient und sicher mit Webdiensten kommuniziert.
Beispiel: Verwendung von HttpRequestMessage Eigenschaften
Hier sehen Sie ein Beispiel für die Verwendung von HttpClient und HttpRequestMessage:
var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com"); // Method and RequestUri usage
using 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`.
Beispiel: Abrufen von umgeleiteten URI
Hier ist ein Beispiel für das Abrufen von umgeleiteten URI (Identisch mit HttpWebRequest.Address):
var client = new HttpClient();
using var response = await client.GetAsync(uri);
var redirectedUri = response.RequestMessage.RequestUri;
Nutzung von SocketsHttpHandler und ConnectCallback
Mit der ConnectCallback Eigenschaft in SocketsHttpHandler können Entwickler den Prozess der Einrichtung einer TCP-Verbindung anpassen. Dies kann für Szenarien hilfreich sein, in denen Sie die DNS-Auflösung steuern oder bestimmte Socketoptionen auf die Verbindung anwenden müssen. Mithilfe von ConnectCallback können Sie den Verbindungsprozess abfangen und ändern, bevor er von HttpClient verwendet wird.
Beispiel: Binden der IP-Adresse an Socket
Im alten Ansatz mit der Verwendung von HttpWebRequest haben Sie möglicherweise benutzerdefinierte Logik verwendet, um eine bestimmte IP-Adresse an einen Socket zu binden. Hier erfahren Sie, wie Sie ähnliche Funktionen mit HttpClient und ConnectCallback verwenden:
Alter Code mit :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();
Neuer Code mit HttpClient und 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);
Beispiel: Anwenden bestimmter Socketoptionen
Wenn Sie bestimmte Socketoptionen anwenden müssen, z. B. das Aktivieren von TCP-Keep-Alive, können Sie ConnectCallback verwenden, um den Socket konfigurieren, bevor er von HttpClient verwendet wird. Tatsächlich ist ConnectCallback flexibler, um Socketoptionen zu konfigurieren.
Alter Code mit :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();
Neuer Code mit HttpClient und 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);
Beispiel: Aktivieren von DNS-Roundrobin
DNS Round Robin ist eine Technik, die verwendet wird, um Den Netzwerkdatenverkehr über mehrere Server zu verteilen, indem sie durch eine Liste der IP-Adressen gedreht wird, die einem einzelnen Domänennamen zugeordnet sind. Dies hilft beim Lastenausgleich und bei der Verbesserung der Verfügbarkeit von Diensten. Bei der Verwendung von HttpClient können Sie DNS Round Robin implementieren, indem Sie die DNS-Auflösung manuell verwalten und durch die IP-Adressen mithilfe der Eigenschaft ConnectCallback von SocketsHttpHandler rotieren.
Um DNS Round Robin mit HttpClient zu aktivieren, können Sie die ConnectCallback-Eigenschaft verwenden, um die DNS-Einträge manuell aufzulösen und die IP-Adressen zu rotieren. Hier ist ein Beispiel für HttpWebRequest und HttpClient:
Alter Code mit :HttpWebRequest
ServicePointManager.DnsRefreshTimeout = 60000;
ServicePointManager.EnableDnsRoundRobin = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
In der älteren HttpWebRequest API war die Aktivierung von DNS Round Robin aufgrund der integrierten Unterstützung für dieses Feature einfach. Die neuere HttpClient API stellt jedoch nicht die gleiche integrierte Funktionalität bereit. Trotzdem können Sie ein ähnliches Verhalten erzielen, indem Sie ein DnsRoundRobinConnector, das manuell durch die IP-Adressen rotiert wird, die von der DNS-Auflösung zurückgegeben werden.
Neuer Code mit 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
Weitere Informationen zur Implementierung finden Sie unter DnsRoundRobinConnectorDnsRoundRobin.cs.
Verwendung von DnsRoundRobinConnector:
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);
}
Beispiel: Festlegen von SocketsHttpHandler Eigenschaften
SocketsHttpHandler ist ein leistungsstarker und flexibler Handler in .NET, der erweiterte Konfigurationsoptionen für die Verwaltung von HTTP-Verbindungen bereitstellt. Indem Sie verschiedene Eigenschaften festlegen SocketsHttpHandler, können Sie das Verhalten Ihres HTTP-Clients optimieren, um bestimmte Anforderungen zu erfüllen, z. B. Leistungsoptimierung, Sicherheitsverbesserungen und benutzerdefinierte Verbindungsbehandlung.
Im Folgenden finden Sie ein Beispiel für die Konfiguration SocketsHttpHandler mit verschiedenen Eigenschaften und deren Verwendung mit 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);
Beispiel: Ändern des Identitätswechsellevels.
Diese Funktionalität ist spezifisch für bestimmte Plattformen und ist etwas veraltet. Wenn Sie eine Problemumgehung benötigen, können Sie sich auf diesen Abschnitt des Codes beziehen.
Verwendung von Zertifikat- und TLS-bezogenen Eigenschaften in HttpClient
Beim Arbeiten mit HttpClient müssen Sie möglicherweise Clientzertifikate für verschiedene Zwecke verarbeiten, z. B. eine benutzerdefinierte Überprüfung von Serverzertifikaten oder das Abrufen des Serverzertifikats.
HttpClient bietet mehrere Eigenschaften und Optionen zum effektiven Verwalten von Zertifikaten.
Beispiel: Überprüfen der Zertifikatsperrliste mit SocketsHttpHandler
Die CheckCertificateRevocationList-Eigenschaft in SocketsHttpHandler.SslOptions ermöglicht Entwicklern, die Überprüfung auf Zertifikatsperrlisten (CRL) während SSL/TLS handshake zu aktivieren oder zu deaktivieren. Durch Aktivieren dieser Eigenschaft wird sichergestellt, dass der Client überprüft, ob das Zertifikat des Servers widerrufen wurde, wodurch die Sicherheit der Verbindung verbessert wird.
Alter Code mit :HttpWebRequest
ServicePointManager.CheckCertificateRevocationList = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Neuer Code mit 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);
Beispiel: Abrufen des Zertifikats
Um das Zertifikat aus dem RemoteCertificateValidationCallback in HttpClient abzurufen, können Sie die ServerCertificateCustomValidationCallback-Eigenschaft von HttpClientHandler oder SocketsHttpHandler.SslOptions verwenden. Mit diesem Callback können Sie das Zertifikat des Servers während des SSL/TLS-Handshakes überprüfen.
Alter Code mit :HttpWebRequest
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
X509Certificate? serverCertificate = request.ServicePoint.Certificate;
Neuer Code mit 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");
Beispiel: Aktivieren der gegenseitigen Authentifizierung
Die gegenseitige Authentifizierung, auch als bidirektionale SSL- oder Clientzertifikatauthentifizierung bezeichnet, ist ein Sicherheitsprozess, bei dem sich sowohl der Client als auch der Server gegenseitig authentifizieren. Dadurch wird sichergestellt, dass beide Parteien deren Anspruch haben, eine zusätzliche Sicherheitsebene für vertrauliche Kommunikationen bereitzustellen. In HttpClient können Sie die gegenseitige Authentifizierung aktivieren, indem Sie HttpClientHandler oder SocketsHttpHandler so konfigurieren, dass das Client-Zertifikat eingeschlossen und das Zertifikat des Servers validiert wird.
Führen Sie die folgenden Schritte aus, um die gegenseitige Authentifizierung zu aktivieren:
- Laden des Clientzertifikats
- Konfigurieren Sie
HttpClientHandleroderSocketsHttpHandler, um das Clientzertifikat einzuschließen. - Richten Sie den Serverzertifikat-Überprüfungscallback ein, wenn eine benutzerdefinierte Überprüfung erforderlich ist.
Hier ist ein Beispiel für die Verwendung von 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);
Verwendung von Headereigenschaften
Header spielen eine wichtige Rolle bei der HTTP-Kommunikation und stellen wesentliche Metadaten über die Anforderung und Antwort bereit. Beim Arbeiten mit HttpClient in .NET können Sie verschiedene Headereigenschaften festlegen und verwalten, um das Verhalten Ihrer HTTP-Anforderungen und -Antworten zu steuern. Wenn Sie wissen, wie Sie diese Headereigenschaften effektiv verwenden, können Sie sicherstellen, dass Ihre Anwendung effizient und sicher mit Webdiensten kommuniziert.
Festlegen von Anforderungsheadern
Anforderungsheader werden verwendet, um dem Server zusätzliche Informationen über die zu stellende Anforderung bereitzustellen. Häufige Anwendungsfälle sind das Angeben des Inhaltstyps, das Festlegen von Authentifizierungstoken und das Hinzufügen von benutzerdefinierten Headern. Sie können Anforderungsheader mithilfe der DefaultRequestHeaders Eigenschaft von HttpClient oder der Headers Eigenschaft von HttpRequestMessage festlegen.
Beispiel: Festlegen von benutzerdefinierten Anforderungsheadern
Festlegen von benutzerdefinierten Standardanforderungsheadern in HttpClient
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Custom-Header", "value");
Festlegen von benutzerdefinierten Anforderungsheadern in HttpRequestMessage
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Add("Custom-Header", "value");
Beispiel: Festlegen allgemeiner Anforderungsheader
Beim Arbeiten mit HttpRequestMessage in .NET ist das Festlegen allgemeiner Anforderungsheader für die Bereitstellung zusätzlicher Informationen an den Server über die zu stellende Anforderung unerlässlich. Diese Header können Authentifizierungstoken und mehr enthalten. Durch die ordnungsgemäße Konfiguration dieser Header wird sichergestellt, dass Ihre HTTP-Anforderungen vom Server ordnungsgemäß verarbeitet werden.
Eine umfassende Liste allgemeiner Eigenschaften, die in HttpRequestHeaders verfügbar sind, finden Sie unter Eigenschaften.
Um allgemeine Anforderungsheader in HttpRequestMessage festzulegen können Sie die Headers-Eigenschaft des HttpRequestMessage-Objekts verwenden. Diese Eigenschaft ermöglicht den Zugriff auf die HttpRequestHeaders-Sammlung, wo Sie bei Bedarf Header hinzufügen oder ändern können.
Festlegen allgemeiner Standardanforderungsheader in HttpClient
using System.Net.Http.Headers;
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "token");
Festlegen allgemeiner Anforderungsheader in HttpRequestMessage
using System.Net.Http.Headers;
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "token");
Beispiel: Festlegen von Inhaltsheadern
Inhaltsheader werden verwendet, um zusätzliche Informationen zum Textkörper einer HTTP-Anforderung oder -Antwort bereitzustellen. Wenn Sie mit HttpClient in .NET arbeiten, können Sie Inhaltsheader festlegen, um den Medientyp, die Kodierung und andere Metadaten anzugeben, die sich auf den gesendeten oder empfangenen Inhalt beziehen. Durch die ordnungsgemäße Konfiguration von Inhaltsheadern wird sichergestellt, dass der Server und der Client den Inhalt richtig interpretieren und verarbeiten können.
var client = new HttpClient();
using 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);
Beispiel: Festlegen MaximumErrorResponseLength in HttpClient
Mithilfe der MaximumErrorResponseLength-Verwendung können Entwickler die maximale Länge des Fehlerantwortinhalts angeben, den der Handler puffert. Dies ist nützlich, um die Datenmenge zu steuern, die gelesen und im Arbeitsspeicher gespeichert wird, wenn eine Fehlerantwort vom Server empfangen wird. Mithilfe dieser Technik können Sie eine übermäßige Speicherauslastung verhindern und die Leistung Ihrer Anwendung bei der Behandlung großer Fehlerantworten verbessern.
Es gibt verschiedene Möglichkeiten, dies zu tun, wir untersuchen die TruncatedReadStream-Technik in diesem Beispiel:
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();
}
}
}
Und Verwendungsbeispiel für 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);
}
Beispiel: CachePolicy Kopfzeilen anwenden
Warnung
HttpClient verfügt nicht über integrierte Logik zum Zwischenspeichern von Antworten. Es gibt keine Andere Problemumgehung als die Implementierung aller Zwischenspeicherung selbst. Das einfache Setzen der Header führt nicht zu einer Zwischenspeicherung.
Bei der Migration von HttpWebRequest zu HttpClient ist die korrekte Handhabung cachebezogene Header wie pragma und cache-control wichtig. Diese Header steuern, wie Antworten zwischengespeichert und abgerufen werden, um sicherzustellen, dass sich Ihre Anwendung hinsichtlich Leistung und Datenfrische erwartungsgemäß verhält.
In HttpWebRequest haben Sie möglicherweise die CachePolicy-Eigenschaft verwendet, um diese Header festzulegen. In HttpClient müssen Sie diese Header jedoch manuell für die Anforderung festlegen.
Alter Code mit :HttpWebRequest
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
In der älteren HttpWebRequest API war die Anwendung von CachePolicy aufgrund der integrierten Unterstützung für dieses Feature einfach. Die neuere HttpClient API stellt jedoch nicht die gleiche integrierte Funktionalität bereit. Trotzdem können Sie ein ähnliches Verhalten erreichen, indem Sie ein AddCacheControlHeaders implementieren, das manuell cachebezogene Header hinzufügt.
Neuer Code mit HttpClient:
public static class CachePolicy
{
public static void AddCacheControlHeaders(HttpRequestMessage request, RequestCachePolicy policy)
Für die Implementierung von AddCacheControlHeaders siehe AddCacheControlHeaders.cs.
AddCacheControlHeadersVerwendung:
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);
}
Verwendung von Puffereigenschaften
Bei der Migration von HttpWebRequest zu HttpClient ist es wichtig, die Unterschiede im Umgang mit der Pufferung dieser beiden APIs zu verstehen.
Alter Code mit :HttpWebRequest
In HttpWebRequest haben Sie direkte Kontrolle über puffernde Eigenschaften über die AllowWriteStreamBuffering und AllowReadStreamBuffering Eigenschaften. Diese Eigenschaften aktivieren oder deaktivieren die Pufferung von Daten, die an den Server gesendet und empfangen werden.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AllowReadStreamBuffering = true; // Default is `false`.
request.AllowWriteStreamBuffering = false; // Default is `true`.
Neuer Code mit HttpClient:
In HttpClient gibt es keine direkten Entsprechungen zu den AllowWriteStreamBuffering und AllowReadStreamBuffering Eigenschaften.
HttpClient erpuffert keine eigenen Anforderungstexte, sondern delegiert die Verantwortung an den HttpContent verwendeten. Inhalte wie StringContent oder ByteArrayContent sind logisch bereits im Arbeitsspeicher gepuffert, während die Verwendung StreamContent standardmäßig keine Pufferung verursacht. Um zu erzwingen, dass der Inhalt gepuffert wird, können Sie vor dem Senden der Anforderung HttpContent.LoadIntoBufferAsync abrufen. Hier sehen Sie ein Beispiel:
HttpClient client = new HttpClient();
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StreamContent(yourStream);
await request.Content.LoadIntoBufferAsync();
using HttpResponseMessage response = await client.SendAsync(request);
In HttpClient ist die Lesepufferung standardmäßig aktiviert. Um dies zu vermeiden, können Sie die HttpCompletionOption.ResponseHeadersRead Flag angeben oder das GetStreamAsync Hilfsprogramm verwenden.
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);