You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 04:53:22