使用HttpClient调用API时无法捕获原始异常的问题咨询
代码示例
StudentService 实现
public class StudentService : IStudentService { private readonly HttpClient _httpClient; private readonly string _baseAdress; private readonly string _url; private readonly JsonSerializerSettings _jsonSerializerSettings; private readonly ILogger<StudentService> _logger; public StudentService(HttpClient httpClient, ILogger<StudentService> logger) { _httpClient = httpClient; _logger = logger; _baseAdress = DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:5000" : "https://localhost:7209"; _url = $"{_baseAdress}/api"; _jsonSerializerSettings = new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }; } public async Task<Student> GetStudentAsync(int id) { var completeUrl = _url + $"/Student/{id}"; try { var response = await _httpClient.GetAsync(completeUrl).ConfigureAwait(false); if (response.IsSuccessStatusCode) { var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); var entity = JsonConvert.DeserializeObject<Student>(json); return entity; } } catch (Exception ex) { _logger.LogError($"{ex}"); throw; } return null; } }
App 类实现
public partial class App : Application { private readonly ILogger<App> _logger; public App(NewPage1 mainPage, ILogger<App> logger) { _logger = logger; AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionTrapper; InitializeComponent(); MainPage = mainPage; } private void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) { var ex = e.ExceptionObject as Exception; _logger.LogError(ex, "Unhandled exception thrown"); } private void UnobservedTaskExceptionTrapper(object sender, UnobservedTaskExceptionEventArgs e) { var ex = e.Exception; _logger.LogError(ex, "Unobserved task exception thrown"); } }
问题描述
我在Android模拟器中调用本地API服务时,应用会在100秒后抛出超时异常并进入中断模式,调试器始终卡在这行代码:
var response = await _httpClient.GetAsync(completeUrl).ConfigureAwait(false);
我知道把端口从5000改成7179后会立刻触发无效证书错误,但我不能直接绕过证书验证。想请教为什么无法捕获原始异常?我已经关闭了Visual Studio的“仅我的代码”功能,但问题还是没解决。
问题分析与解决
为什么抓不到原始异常?
- 默认的
HttpClientHandler遇到证书验证失败时,不会立即抛出异常,而是会持续尝试建立连接直到超时。最终抛出的是超时异常,而非证书错误本身。 - 全局异常处理器(
UnhandledException和UnobservedTaskException)无法捕获原始异常,因为任务处于等待状态时异常并未触发,直到超时后才抛出超时异常。
可行的解决方法
- 自定义证书验证逻辑:不直接绕过证书,而是验证本地开发证书的指纹,确保请求只信任自己的API证书:
var handler = new HttpClientHandler(); handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { // 替换为你本地API证书的指纹 var localCertThumbprint = "你的证书指纹字符串"; return cert.Thumbprint.Equals(localCertThumbprint, StringComparison.OrdinalIgnoreCase); }; var httpClient = new HttpClient(handler); - 缩短超时时间:临时将
HttpClient的超时时间调短(比如10秒),快速确认是否是证书问题导致的连接失败,避免等待100秒才触发异常:_httpClient.Timeout = TimeSpan.FromSeconds(10); - 增强日志排查:在
catch块中补充请求地址、响应状态码等信息,帮助定位问题:try { _logger.LogInformation("请求地址:{Url}", completeUrl); var response = await _httpClient.GetAsync(completeUrl).ConfigureAwait(false); _logger.LogInformation("响应状态码:{StatusCode}", response.StatusCode); // 后续业务代码 } catch (Exception ex) { _logger.LogError(ex, "请求失败,地址:{Url}", completeUrl); throw; }
内容的提问来源于stack exchange,提问作者Sigidd
相关产品推荐
相关产品推荐

