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

如何避免HttpClient中查询字符串的双重编码问题?

解决HttpClient查询字符串双重编码问题

这个双重编码问题的核心原因是:你的BuildUrl方法已经对查询参数完成了编码,但当你把编码后的字符串传给HttpClient.GetAsync时,HttpClient会把这个字符串当作未编码的原始内容,再次对其中的特殊字符(比如%)进行编码,最终导致%u00fa变成%25u00fa(%被编码为%25)。

解决方案:传递Uri对象而非字符串给GetAsync

HttpClient对Uri类型的参数会正确识别其编码状态,不会重复编码。你只需要修改BuildUrl方法返回Uri对象,而不是字符串即可:

修改后的BuildUrl方法

private Uri BuildUrl(string baseUrl, NameValueCollection urlParameters)
{
    var builder = new UriBuilder(baseUrl);
    if (urlParameters != null)
    {
        var query = HttpUtility.ParseQueryString(builder.Query);
        query.Add(urlParameters);
        builder.Query = query.ToString();
    }
    return builder.Uri; // 返回Uri对象,而非字符串
}

对应的MakeGetCall方法调整

private async Task<string> MakeGetCall(string apiVersion, string url, string accessToken, NameValueCollection urlParameters = null) 
{ 
    var client = GetHttpClient(); 
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(Constants.AUTHORIZATION_HEADER_VALUE_CONST_PART, accessToken); 
    // 直接传递Uri对象,避免二次编码
    var result = await client.GetAsync(BuildUrl(apiVersion + url, urlParameters)); 
    result.EnsureSuccessStatusCode(); // 原代码的EnsureSuccess()应为标准方法EnsureSuccessStatusCode(),若为自定义扩展可忽略
    return await result.Content.ReadAsStringAsync(); 
}

为什么这个方法有效?

  • UriBuilder.Uri会返回一个已经正确编码的Uri实例,其中的查询参数编码符合RFC 3986标准。
  • 当HttpClient接收Uri类型参数时,会直接使用其已有的编码结果,不会再对%等字符进行二次编码。

内容的提问来源于stack exchange,提问作者Igor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:17:23