为什么HttpClient BaseAddress不起作用?

考虑以下代码,其中BaseAddress定义了部分URIpath。

 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 。 但事实并非如此。

经过一番search,我发现这个问题和答案: 与BaseAddress HttpClient 。 build议放置在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这是怎么回事?

事实certificate,在包含或排除BaseAddress尾随或前导斜杠以及传递给GetAsync方法的相对URI或HttpClient其他方法的四种可能排列中,只有一种排列GetAsync 。 您必须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"); } 

即使我回答了我自己的问题,但我想我会在这里提供解决scheme,因为这种不友好的行为是没有证据的。 我的同事和我花了大部分时间试图解决这个问题,这个问题最终是由这个奇怪的HttpClient引起的。

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

如果基URI包含非空path,则合并过程将丢弃它的最后部分(在last / )。 相关部分 :

5.2.3。 合并path

上面的伪代码是指一个“合并”例程,用于将相对path引用与基本URI的path合并。 这是如下完成的:

  • 如果基本URI有一个定义的权限组件和一个空path,则返回一个由引用path连接的“/”组成的string; 除此以外

  • 返回由引用的path组件组成的string,该组件附加到基本URIpath的最后一个段(除了基本URIpath中最右侧的“/”之后的所有字符,或者排除整个基本URIpath不包含任何“/”字符)。

如果相对URI以斜杠开始,则称为绝对path相对URI。 在这种情况下,合并过程忽略所有的基本URIpath。 有关更多信息,请查阅5.2.2。 转换参考部分。