C# HttpClient Une connexion existante a dû être fermée par l'hôte distant
Je suis en train de travailler sur une intégration avec les autres modes de paiement à l'aide de leur page hébergée intégration. De leur C# SDK ne dispose pas de cette intégration disponible pour le moment, mais comme vous pouvez le voir c'est assez simple et j'ai fait une petite classe pour envoyer la requête post et obtenir la réponse JSON.
J'ai testé l'objet json je suis de l'envoyer sur le Facteur et les boucles et les deux travaillent, aussi l'en-tête d'authentification, donc je pense qu'ils ne sont pas le problème. Voici le constructeur de ma classe:
public AlternativePaymentsCli(string apiSecretKey)
{
this._apiSecretKey = apiSecretKey;
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var authInfo = _apiSecretKey;
authInfo = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:", _apiSecretKey)));
//The two line below because I saw in an answer on stackoverflow.
_httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
_httpClient.DefaultRequestHeaders.Add("Keep-Alive", "3600");
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Anything.com custom client v1.0");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
}
Et la méthode où je suis à la publication des données:
public string CreateHostedPageTransaction(HostedPageRequest req)
{
var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
//I send this same json content on PostMan and it works. The json is not the problem
var content = new StringContent(JsonConvert.SerializeObject(req, settings), Encoding.UTF8, "application/json");
var response = _httpClient.PostAsync(this._baseUrl + "/transactions/hosted", content).Result;
var responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
return responseText;
return "";
}
Puis, j'obtiens cette erreur: An existing connection was forcibly closed by the remote host
, à la PostAsync ligne. C'est les détails de l'erreur:
[SocketException (0x2746): An existing connection was forcibly closed by the remote host]
System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) +8192811
System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult) +47
[IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.]
System.Net.TlsStream.EndWrite(IAsyncResult asyncResult) +294
System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar) +149
[WebException: The underlying connection was closed: An unexpected error occurred on a send.]
System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context) +324
System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar) +137
[HttpRequestException: An error occurred while sending the request.]
Je suis à l'aide de C# 4.5, Asp.Net MVC. J'ai lu des réponses pour le même message d'erreur et aucun n'a résolu mon problème jusqu'à présent. Ce qui me manque dans ce code?
Merci pour toute aide
- Qu'est-ce que vous voyez dans la réponse dans un violon?
- Juste une astuce sympa, à l'aide de
var
pour tout ce qui fera de vos collègues de travail que vous détestez. Utilisez uniquementvar
lorsque le type est évident (j'.evar date = new DateTime();
) son très clairement unDateTime
. Cependantvar response = _httpClient.PostAsync(this._baseUrl + "/transactions/hosted", content).Result;
n'est pas clair car.Result
est une propriété et non implicite de quel type il est. - au contraire, à l'aide de
var
rend le code beaucoup plus propre. Il n'y a aucune ambiguïté sur le type, sauf si vous écrivez vraiment long méthodes, dans ce cas, vous devriez vraiment, vraiment séparez. Vos collègues vous hais si vous écrivez des méthodes qui sont si longs qu'ils ne peuvent pas voir ce que les types sont var
seulement rend le code plus propre quand le type est implicite, à l'aide devar
partout (même dans les cas où le type n'est pas implicite) est tout simplement mauvaise programmation.- comme pour
.Result
, des collègues de travail haïr personne qui bloque un appel asynchrone avec.Wait()
ou.Result
. Le type de retour est connue de toute façon. C'est HttpResponseMessage. En voyant le nom ne vous aidera pas que vous aurez à utiliser intellisense de toute façon trouver des méthodes à utiliser - qui, par exemple, est pourquoi les langages fonctionnels utiliser l'inférence de type au lieu de spécifier le type explicitement, Vous ne pouvez pas être familier avec l'inférence de type. Ce n'en est pas mauvaise programmation. D'autre part, un appel à
.Result
devrait soulever quelqu'un de l'indignation - est-il vraiment connu? Ignorant expérience préalable dans toute bibliothèque de la .NET, quel est le moyen le plus facile pour moi de connaître le type? (Son en la déclarant dans les cas où il est pas de manière redondante implicite.
- et oui, je suis d'accord que l'OP ne doit pas être bloquant les appels asynchrones (si elle n'était pas déjà le savoir, le code que j'ai posté est directement à partir de l'OP est question et pas le mien).
- Totalement hors. Je ne sais pas qui l'IDe que vous utilisez, j'utilise Visual Studio et lorsque vous placez le pointeur de la variable qu'il vous dit le type. Merci
- Double Possible de Une connexion existante a dû être fermée par l'hôte distant
Vous devez vous connecter pour publier un commentaire.
Je ne vois pas dans votre exemple de code où vous définissez la valeur de _baseUrl, mais je suppose que c'est fait quelque part. Je suis aussi en supposant que, depuis ce relatives aux paiements, l'URL est de type HTTPS. Si l'hôte distant a désactivé le protocole TLS 1.0 et votre connexion est de venir en TLS 1.0, il pourrait causer ce comportement. Je sais que C# 4.6 a TLS 1.0/1.1/1.2 support activé par défaut, mais je pense que C# 4.6 encore défaut à seulement SSL3/TLS 1.0, même si TLS 1.1 et 1.2 sont pris en charge. Si c'est la cause du problème, vous pouvez ajouter manuellement TLS 1.1 et 1.2 de l'activé en utilisant le code suivant.
Si vous êtes en utilisant .Net 4.0, puis SecurityProtocolType.Tls11 et SecurityProtocolType.Tls2 ne sont pas définis de façon à la place, vous pouvez utiliser la valeur établie dans le code ci-dessous.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;