考虑下面的代码,其中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");
}
我期望它执行到http://something.com/api/resource/7的GET请求。但事实并非如此。
经过一些搜索,我找到了这个问题和答案: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。这里发生了什么?
如果你正在使用httpClient.SendAsync(),就不会像Get或其他特定于动词的方法那样重载相对uri的字符串。
但是你可以通过给UriKind创建相对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();
我也遇到了同样的问题与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的利弊,但对我来说,这是完美无缺的。希望这能帮助到一些人。
引用解析由RFC 3986统一资源标识符(URI):通用语法描述。而这正是它应有的运作方式。为了保留基本URI路径,您需要在基本URI的末尾添加斜杠,并在相对URI的开头删除斜杠。
如果基URI包含非空路径,合并过程将丢弃其最后一部分(在last /之后)。相关部门:
5.2.3. 合并路径
上面的伪代码引用了用于合并的“merge”例程
使用基本URI路径的相对路径引用。这是
完成如下工作:
如果基本URI具有已定义的权限组件和空
路径,然后返回由"/"连接到
参考的路径;否则
返回由引用的路径组件组成的字符串
附加到除了基URI路径的最后一段之外的所有部分(即,
排除基URI中最右边的“/”后面的任何字符
路径,或排除整个基本URI路径,如果它不包含
任何“/”字符)。
如果相对URI以斜杠开头,则称为绝对路径相对URI。在这种情况下,合并过程忽略所有基本URI路径。更多信息请查看5.2.2。“转换引用”部分。