Curl脚本可正常获取API数据,C#代码在服务器上失效求排查
C# HttpClient调用API失败排查与修复
问题情况
在服务器上使用Curl脚本可正常从API的GET链接获取JSON数据,但用C#代码调用却无法获取相同数据;基于.NET Core搭建的自有GET API在本地运行正常,部署到服务器后失效。修改代码后,文本文件未写入JSON数据,而是写入了System.Net.Http.StreamContent;通过批处理文件运行应用时,有时命令行能显示JSON,但exe或文本写入无法输出正确内容。
可用的Curl脚本
curl -H "Host: enabler-api.com.baeldung" https://localhost:8080/api/IQueue
原C#代码
using System.IO; using NewtonSoft.Json; using System.Net.Http.Json; private async void btn1_Click(object sender, RoutedEventArgs e) { HttpClient client = new HttpClient(); string filepath = "C:/Desktop/response1.txt"; var response = await client.GetAsync("https://localhost:8080/api/IQueue"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Host", "enabler-api.com.baeldung"); response.EnsureSuccessStatusCode(); JsonSerializer Serializer = new JsonSerializer(); if (response.IsSuccessStatusCode) { //parse json, convert json to string using(StreamWriter sw = new StreamWriter(filepath)) using(JsonWriter writer = new JsonTextWriter(sw)) { var rt = response.Content.ReadFromJsonAsync<IEnumerable<iqueue>>().Result; Serializer.Serialize(writer, rt); MessageBox.Show(rt.ToList().ToString()); usergrid.ItemsSource = rt; } } else { MessageBox.Show("Error Code" + response.StatusCode + ": Message - "+ response.ReasonPhrase); } }
问题分析
- 请求头设置时机错误:原代码先执行
GetAsync发送请求,之后才添加Accept和Host头,这些头根本不会被包含在本次请求中,等于无效设置。 - Host头设置方式错误:用
AuthenticationHeaderValue设置Host头是完全错误的,Host是标准HTTP请求头,应直接添加到DefaultRequestHeaders集合中。 - 异步调用阻塞问题:使用
.Result阻塞异步方法ReadFromJsonAsync,容易引发死锁或异常,应使用await关键字。 - 序列化逻辑冗余且错误:同时混用
System.Net.Http.Json和Newtonsoft.Json,且序列化步骤有误,导致写入错误内容。 - 服务器路径权限问题:服务器上可能不存在
C:/Desktop路径,或应用无写入权限,导致文件写入失败。
修正后的C#代码
using System.IO; using Newtonsoft.Json; using System.Net.Http.Headers; using System; private async void btn1_Click(object sender, RoutedEventArgs e) { // 使用using确保HttpClient正确释放 using (HttpClient client = new HttpClient()) { // 服务器上建议使用相对路径或有权限的目录,比如应用程序所在目录 string filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "response1.txt"); // 先设置请求头,再发送请求 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // 正确设置Host头 client.DefaultRequestHeaders.Host = "enabler-api.com.baeldung"; try { var response = await client.GetAsync("https://localhost:8080/api/IQueue"); response.EnsureSuccessStatusCode(); // 抛出HTTP错误状态码异常 if (response.IsSuccessStatusCode) { // 用await异步读取数据,避免阻塞 var rt = await response.Content.ReadFromJsonAsync<IEnumerable<iqueue>>(); // 使用Newtonsoft.Json序列化到文件 using (StreamWriter sw = new StreamWriter(filepath)) using (JsonTextWriter writer = new JsonTextWriter(sw)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(writer, rt); } // 显示数据时不要直接ToString集合,应展示具体内容 MessageBox.Show(JsonConvert.SerializeObject(rt)); usergrid.ItemsSource = rt; } } catch (HttpRequestException ex) { MessageBox.Show($"请求错误: {ex.Message}"); } catch (Exception ex) { MessageBox.Show($"未知错误: {ex.Message}"); } } }
额外注意事项
- 服务器部署时,确保应用程序有目标目录的写入权限,避免使用本地固定路径(如C:/Desktop),改用应用程序所在目录或配置的合法路径。
- 若API使用HTTPS,需确保服务器信任证书,或在HttpClient中配置忽略证书验证(仅测试环境使用)。
- 避免使用
async void,建议改用async Task(对于事件处理方法async void是允许的,但需注意异常处理)。
内容的提问来源于stack exchange,提问作者alex dave
相关产品推荐
相关产品推荐

