如何避免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
相关产品推荐
相关产品推荐

