为什么HttpClient BaseAddress不起作用?

时间:2014-05-02 23:25:07

标签: c# .net dotnet-httpclient

考虑以下代码,BaseAddress定义部分URI路径。

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api");
    var response = await client.GetAsync("/resource/7");
}

我希望这会向GET执行http://something.com/api/resource/7请求。但事实并非如此。

经过一番搜索,我发现了这个问题并回答:HttpClient with BaseAddress。建议将/放在BaseAddress的末尾。

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("/resource/7");
}

它仍然不起作用。这是文档:HttpClient.BaseAddress这里发生了什么?

6 个答案:

答案 0 :(得分:509)

事实证明,在BaseAddress中包含或排除尾随或前导斜杠的四种可能排列中,以及传递给GetAsync方法的相对URI - 或者其他任何方法HttpClient - 仅一个排列有效。您必须BaseAddress的末尾添加斜杠,不得在相对URI的开头放置斜杠,如下例所示

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("resource/7");
}

尽管我回答了自己的问题,但我认为我会在这里提供解决方案,因为这种不友好的行为再次没有记录。我和我的同事大部分时间都在努力解决最终由HttpClient这种奇怪问题引起的问题。

答案 1 :(得分:30)

参考分辨率由RFC 3986 Uniform Resource Identifier (URI): Generic Syntax描述。这正是它应该如何运作的。要保留基URI路径,您需要在基URI的末尾添加斜杠,并在相对URI的开头删除斜杠。

如果基URI包含非空路径,则合并过程会丢弃它的最后一部分(在最后/之后)。相关的section

  

<强> 5.2.3。合并路径

     

上面的伪代码是指用于合并a的“合并”例程   相对路径引用与基URI的路径。这是   完成如下:

     
      
  • 如果基URI具有已定义的权限组件且为空     path,然后返回一个由“/”连接的字符串     参考路径;否则

  •   
  • 返回由引用的路径组件组成的字符串     附加到除基本URI路径的最后一段之外的所有段(即     排除基URI中最右边的“/”之后的任何字符     路径,或者如果不包含整个基本URI路径,则将其排除     任何“/”字符。

  •   

如果相对URI以斜杠开头,则称为绝对路径相对URI。在这种情况下,合并过程忽略所有基URI路径。有关详细信息,请查看5.2.2. Transform References部分。

答案 2 :(得分:3)

或者-完全不使用BaseAddress。将整个网址放入GetAsync()

答案 3 :(得分:1)

我也遇到了与 BaseAddress 相同的问题。我决定根本不使用 BaseAddress,最简单的解决方案是简单的单行添加:

Uri GetUri(string path) => new Uri("http://something.com/api" + path);

那么你的代码会变成:

Uri GetUri(string path) => new Uri("http://something.com/api" + path);
using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    // Remove BaseAddress completely
    // client.BaseAddress = new Uri("http://something.com/api");
    var response = await client.GetAsync(GetUri("/resource/7"));
}

我还没有调查过使用 BaseAddress 的利弊,但对我来说这完美无缺。希望这对某人有所帮助。

答案 4 :(得分:1)

如果您使用的是 httpClient。SendAsync() 没有像 Get、Post 和其他动词特定方法中的重载那样的字符串重载。

但是您可以通过将 UriKind.Relative 作为第二个参数来创建相对 Uri

        var httpRequestMessage = new HttpRequestMessage
        {
            Method = httpMethod,
            RequestUri = new Uri(relativeRequestUri, UriKind.Relative),
            Content = content
        };

        using var httpClient = HttpClientFactory.CreateClient("XClient");
        var response = await httpClient.SendAsync(httpRequestMessage);
        var responseText = await response.Content.ReadAsStringAsync();

答案 5 :(得分:0)

HTTPClient出现问题,即使提出建议仍无法对其进行身份验证。事实证明,我在相对路径中需要尾随“ /”。

var result = await _client.GetStringAsync(_awxUrl + "api/v2/inventories/?name=" + inventoryName);
var result = await _client.PostAsJsonAsync(_awxUrl + "api/v2/job_templates/" + templateId+"/launch/" , new {
                inventory = inventoryId
            });