Ich versuche, einen Layer für den Webservice mit HttpClient in meiner Xamarin.Forms
-App zu erstellen.
in first approach Ich erstelle in jeder neuen Anfrage ein neues http-Client-Objekt durch mobile Anwendung.
hier ist mein code
public HttpClient GetConnection()
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(baseAddress);
httpClient.Timeout = System.TimeSpan.FromMilliseconds(timeout);
return httpClient;
}
anforderungscode posten
public async Task<TResult> PostAsync<TRequest, TResult>(String url, TRequest requestData)
{
HttpClient client = GetConnection();
String responseData = null;
if (client != null)
{
String serializedObject = await Task.Run(() => JsonConvert.SerializeObject(requestData, _jsonSerializerSettings));
var jsonContent = new StringContent(serializedObject, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(new Uri(url, UriKind.Relative), jsonContent);
responseData = await HandleResponse(response);
return await Task.Run(() => JsonConvert.DeserializeObject<TResult>(responseData, _jsonSerializerSettings));
}
else
{
throw new NullReferenceException("NullReferenceException @ PostAsync httpclient is null WebRequest.cs");
}
}
der Client verwendet folgenden Code, um die Anforderung auszuführen
new LoginService(new WebRequest()).UserLogin(userRequest);
innerhalb der Klasse, die IWebRequest
implementiert
_webRequest.PostAsync<UserRequest,bool>(Constants.USER_LOGIN, userRequest);
in second approach verwende ich dasselbe http-Client-Objekt in jeder neuen Anfrage Hier ist meine Singleton-Klasse auch threadsicher.
private static readonly Lazy<HttpService> lazy =
new Lazy<HttpService>(() => new HttpService());
public static HttpService Instance { get { return lazy.Value; } }
private HttpClient getConnection()
{
client = new HttpClient();
client.Timeout = System.TimeSpan.FromMilliseconds(timeout);
//client.MaxResponseContentBufferSize = 500000;
client.BaseAddress = new Uri(baseAddress);
return client;
}
anforderungscode posten
public Task<HttpResponseMessage> sendData(String url,String jsonData)
{
var jsonContent = new StringContent(jsonData, System.Text.Encoding.UTF8, "application/json");
return getConnection().PostAsync(new Uri(url, UriKind.Relative), jsonContent);
}
der Client verwendet folgenden Code zur Ausführung
HttpService.Instance.sendData(...)
ich bin durch viele Bibliotheken wie RestSharp
über das Web gegangen, um das Beste zu erkunden, und ich habe festgestellt, dass die meisten von ihnen neue Objekte pro Anfrage erstellen. Ich bin verwirrt, welches Muster am besten passt.
Update: Es scheint, dass die Verwendung einer einzelnen statischen Instanz von HttpClient
keine DNS-Änderungen berücksichtigt. Daher besteht die Lösung in der Verwendung von HttpClientFactory
. Unter hier finden Sie Microsoft-Dokumente.
Singleton ist die richtige Art, HttpClient
zu verwenden. Bitte sehen Sie this article für vollständige Details.
Microsoft docs state:
HttpClient soll einmalig instanziiert werden und während der gesamten Lebensdauer einer Anwendung wiederverwendet werden. Durch das Instanziieren einer HttpClient-Klasse für jede Anforderung wird die Anzahl der unter schwerer Last verfügbaren Steckdosen erschöpft. Dies führt zu SocketException-Fehlern. Unten ist ein Beispiel, das HttpClient korrekt verwendet.
Und tatsächlich haben wir dies in unserer Anwendung gefunden. Wir haben Code, der potenziell Hunderte von API-Anforderungen in einer foreach
-Schleife auslösen kann. Für jede Iteration haben wir eine HttpClient
erstellt, die in eine using
eingeschlossen ist. Schon bald bekamen wir rote Heringsfehler von unserer MongoClient
und sagten, dass es beim Versuch, eine Verbindung zur Datenbank herzustellen, abgelaufen war. Nachdem wir den verlinkten Artikel gelesen hatten, stellten wir fest, dass HttpClient
entsorgt wurde, und stellten fest, dass wir die verfügbaren Sockel erschöpften.
Das einzige, was zu beachten ist, ist, dass Dinge wie DefaultRequestHeaders
und BaseAddress
überall dort angewendet werden, wo HttpClient verwendet wird. Als Singleton gilt dies möglicherweise für die gesamte Anwendung. Sie können immer noch mehrere HttpClient
-Instanzen in Ihrer Anwendung erstellen. Beachten Sie jedoch, dass sie jedes Mal einen neuen Verbindungspool erstellen und daher sparsam erstellt werden sollten.
Wie von hvaughan3 hervorgehoben, können Sie auch die vom HttpClient verwendete Instanz von HttpMessageHandler
nicht ändern. Wenn dies für Sie wichtig ist, müssen Sie mit diesem Handler eine separate Instanz verwenden.
Während HttpClient
wiederverwendet werden soll, bedeutet dies nicht notwendigerweise, dass wir Singleton verwenden müssen, um unseren Code zu organisieren. Bitte beziehen Sie sich auf meine Antwort hier .
PS: Nicht sicher, ob ich diese Antwort hier kopieren und einfügen soll. Gib mir Bescheid.
Wie bereits erwähnt, sollte meist HttpClient
als Singleton verwendet werden, es gibt jedoch eine Ausnahme - Sie sollten HttpClient
nicht als Singleton verwenden, wenn Sie die HTTP long polling
-Technik verwenden, da Sie die Ausführung anderer Anforderungen blockieren.
Für lange Abrufanfragen sollten Sie eine separate HttpClient
erstellen.