.NET Framework 4.5.2 C#桌面应用调用REST API遇连接错误求助
我用.NET Framework 4.5.2开发C#桌面应用,调用API获取Token时遇到以下错误,该请求在Postman中可正常运行:
One or more errors occurred.System.Net.Http.HttpRequestException: An error occurred while sending the request. --->
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. --->
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. --->
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
我的代码如下:
string username = "username"; string password = "password"; string apiUrl = "https://.../auth/token"; var httpClientHandler = new HttpClientHandler { AllowAutoRedirect = false, UseCookies = false }; using (var httpClient = new HttpClient(httpClientHandler)) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}")) ); var requestContent = new StringContent( "{ \"terminal_id\": \"95000059\" }", System.Text.Encoding.UTF8, "application/json" ); try { var response = httpClient.PostAsync(apiUrl, requestContent).Result; if (response.IsSuccessStatusCode) { var responseContent = response.Content.ReadAsStringAsync().Result; richTextBox1.Text = responseContent; } else { richTextBox1.Text = $"Failed to get token. Status code: {response.StatusCode}"; } } catch (HttpRequestException ex) { richTextBox1.Text = ex.Message; } }
解决方法
1. 启用TLS 1.2支持
.NET Framework 4.5.2默认未启用TLS 1.2,而多数现代API服务器仅支持TLS 1.2及以上版本,Postman默认兼容该协议,这是最可能的问题根源。在创建HttpClient前添加以下代码:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
修改后的完整代码示例:
string username = "username"; string password = "password"; string apiUrl = "https://.../auth/token"; // 启用TLS 1.2 System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; var httpClientHandler = new HttpClientHandler { AllowAutoRedirect = false, UseCookies = false }; using (var httpClient = new HttpClient(httpClientHandler)) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}")) ); var requestContent = new StringContent( "{ \"terminal_id\": \"95000059\" }", System.Text.Encoding.UTF8, "application/json" ); try { var response = httpClient.PostAsync(apiUrl, requestContent).Result; if (response.IsSuccessStatusCode) { var responseContent = response.Content.ReadAsStringAsync().Result; richTextBox1.Text = responseContent; } else { richTextBox1.Text = $"Failed to get token. Status code: {response.StatusCode}"; } } catch (HttpRequestException ex) { richTextBox1.Text = ex.Message; } }
2. 对齐请求头与Postman配置
对比Postman中的请求头,确保代码包含所有必要字段。例如Postman会自动添加User-Agent,可手动补充:
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36");
3. 改用异步调用模式(可选)
使用.Result同步调用异步方法可能引发死锁或异常,建议改为异步写法:
private async void GetTokenAsync() { string username = "username"; string password = "password"; string apiUrl = "https://.../auth/token"; System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; var httpClientHandler = new HttpClientHandler { AllowAutoRedirect = false, UseCookies = false }; using (var httpClient = new HttpClient(httpClientHandler)) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($"{username}:{password}")) ); var requestContent = new StringContent( "{ \"terminal_id\": \"95000059\" }", System.Text.Encoding.UTF8, "application/json" ); try { var response = await httpClient.PostAsync(apiUrl, requestContent); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); richTextBox1.Text = responseContent; } else { richTextBox1.Text = $"Failed to get token. Status code: {response.StatusCode}"; } } catch (HttpRequestException ex) { richTextBox1.Text = ex.Message; } } }
内容的提问来源于stack exchange,提问作者Orgil

