J'essaie de créer une couche pour le service Web à l'aide de HttpClient dans mon application mobile Xamarin.Forms
.
dans premier approche, je crée un nouvel objet client http dans chaque nouvelle demande faite par application mobile.
voici mon code
public HttpClient GetConnection()
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(baseAddress);
httpClient.Timeout = System.TimeSpan.FromMilliseconds(timeout);
return httpClient;
}
poste demande code
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");
}
}
le client utilisera le code suivant pour exécuter la demande
new LoginService(new WebRequest()).UserLogin(userRequest);
dans la classe qui implémente IWebRequest
_webRequest.PostAsync<UserRequest,bool>(Constants.USER_LOGIN, userRequest);
in second approche Je réutilise le même objet client http dans chaque nouvelle requêtehere, ma classe singleton est thread-safe aussi.
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;
}
poste demande code
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);
}
le client utilisera le code suivant pour exécuter
HttpService.Instance.sendData(...)
j'ai parcouru de nombreuses bibliothèques telles que RestSharp
sur le Web uniquement pour explorer le meilleur et j'ai constaté que la plupart d'entre elles créent de nouveaux objets à la demande. je ne comprends donc pas quel modèle convient le mieux.
Update: Il semble que l'utilisation d'une seule instance statique de HttpClient
ne respecte pas les modifications DNS. La solution consiste donc à utiliser HttpClientFactory
. Voir ici pour Microsoft docs à ce sujet.
Singleton est la manière correcte d’utiliser HttpClient
. S'il vous plaît voir this article pour plus de détails.
Microsoft docs state:
HttpClient est destiné à être instancié une fois et réutilisé tout au long de la vie d'une application. L'instanciation d'une classe HttpClient pour chaque requête épuise le nombre de sockets disponibles sous des charges lourdes. Cela entraînera des erreurs SocketException. Vous trouverez ci-dessous un exemple d'utilisation correcte de HttpClient.
Et en effet, nous avons trouvé cela dans notre application. Nous avons du code qui peut potentiellement faire des centaines de demandes d'API dans une boucle foreach
, et pour chaque itération, nous avons créé une HttpClient
encapsulée dans une using
. Nous avons rapidement commencé à avoir des erreurs de hareng rouge de notre MongoClient
en disant que le délai imparti à sa connexion à la base de données avait expiré. Après avoir lu l'article lié, nous avons constaté que même après avoir disposé de HttpClient
, nous avons réalisé que nous épuisions les sockets disponibles.
La seule chose à noter est que des éléments tels que DefaultRequestHeaders
et BaseAddress
seront appliqués partout où HttpClient est utilisé. En tant que singleton, c'est potentiellement tout au long de l'application. Vous pouvez toujours créer plusieurs instances HttpClient
dans votre application, mais sachez que chaque fois que vous le faites, elles créent un nouveau pool de connexions et doivent donc être créées avec parcimonie.
Comme l'a souligné hvaughan3, vous ne pouvez pas non plus modifier l'instance de HttpMessageHandler
utilisée par HttpClient. Par conséquent, si cela vous concerne, vous devez utiliser une instance distincte avec ce gestionnaire.
Bien que HttpClient
soit censé être réutilisé, cela ne signifie pas nécessairement que nous devons utiliser singleton pour organiser notre code. Veuillez vous référer à ma réponse ici .
PS: Je ne sais pas si je suis censé copier et coller cette réponse ici. Faites le moi savoir.
Comme d'autres l'ont mentionné, HttpClient
devrait être utilisé principalement en tant que singleton, à une exception près: vous ne devez pas utiliser HttpClient
en tant que singleton lorsque vous utilisez la technique HTTP long polling
, car vous bloquerez l'exécution d'autres requêtes.
Pour les demandes d'interrogation longues, vous devez créer une variable HttpClient
séparée.