请考虑以下代码,其中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请求。但是没有。

经过一番搜索,我找到了这个问题并回答:带有BaseAddress的HttpClient。建议将/放在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这是怎么回事?

评论

可能与具有BaseAddress
的HttpClient重复
@ГеоргийЛанец已经提出反向重复。我之所以写这个问题,是因为其他问题不是以同样的问题的人很容易发现的方式写的,而我之所以在这里写下答案,是因为那里的答案遗漏了一个重要的观点。

但是稍后会问这个问题

@ГеоргийЛанец这不是它的工作原理。通常,最“规范”的问题是使指向该问题的重复项的问题。另一个问题是关于用户遇到的一个问题,而不是像常见问题解答那样阅读。

@ГеоргийЛанец同时请注意,我引用了该问题中的另一个问题,并解释了为什么另一个问题和答案不足以解决问题。

#1 楼

事实证明,在包括或排除BaseAddress上的尾随或前斜杠和传递给GetAsync方法(或HttpClient的任何其他方法)的相对URI的四个可能置换中,只有一个置换有效。您必须在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的这种怪异而导致的问题。

评论


谢谢。这解决了我在两天的大部分时间里一直在苦苦挣扎的问题,在切换到Azure,回到IIS和再回到IIS Express之间,这最不礼貌地忽略了放错位置或多余的正斜杠。一旦在我的RestClient的基类中设置了它,它几乎是不可见的,根本没有引起任何注意,并且我在断点等处从未看到完整的URL。

– ProfK
16/12/13在14:32



我可以确认这种怪异(和此修复程序)在.NET Core中仍然有用。感谢您减少我的头发提摩太。

–内特·巴贝蒂尼(Nate Barbettini)
17 Mar 29 '17 at 19:32

这是因为在生成请求时不加任何斜杠,它会丢弃最后一部分。因此,它访问了something.com/resource/7。如果您将基址设置为something / com(是否带斜杠也没关系),则将斜杠放在api / resource / 7的开头也没关系。没有尾部斜杠时,基地址的最后部分被视为文件,并在建立请求时删除。

–彼得·霹雳
17-6-27 at 7:52



这不是直接解决原始问题,而是相关的。对于每个Mircosoft,应将HttpClient()的实例分配给静态变量并重用(docs.microsoft.com/zh-cn/aspnet/web-api/overview/advanced/…-每个请求创建一个新的HttpClient实例都会耗尽可用的套接字)。因此,您应该考虑删除Using()。

– sanmcp
17年12月11日在3:24



只是一个可怕的实现。他们为什么不解决这个问题?

–timmkrause
18-10-30在16:14

#2 楼

参考解析由RFC 3986统一资源标识符(URI):通用语法描述。这正是它应该如何工作的。要保留基本URI路径,您需要在基本URI的末尾添加斜杠,并在相对URI的开始处删除斜杠。

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


5.2.3。合并路径

上面的伪代码引用了一个“合并”例程,用于将相对路径引用与基本URI的路径合并。这是通过以下步骤完成的:


如果基本URI具有已定义的权限组件和空的
路径,则返回由“ /”串联而成的字符串带有
引用的路径;否则
返回一个字符串,该字符串包含引用的路径部分组成的字符串
,附加到基本URI路径的最后一段以外的所有部分(即,
不包括最右端“ /”后面的任何字符)基本URI
路径,如果不包含任何


如果是相对URI以斜杠开头,它称为绝对路径相对URI。在这种情况下,合并过程将忽略所有基本URI路径。有关更多信息,请检查5.2.2。变换参考部分。

评论


很好,但是客户端库(例如HttpClient)应该使我们免受诸如此类的深奥实现细节的困扰。

–杰米·艾德(Jamie Ide)
20年1月16日在15:11

答案涵盖原因为何如此有效,并带有相关的链接和引号非常好。即使这对直接解决问题没有帮助,也很有帮助。

–Rast
20年6月21日在16:18

#3 楼

即使提出了建议,HTTPClient仍然存在问题,无法对其进行身份验证。原来我在相对路径中需要尾随'/'。

ie

 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
            });