【知识点】Uri对象的完整地址

通过HttpClient发送请求时,可以先设置BaseAddress,之后的请求直接传入相对地址即可:

1 using(var httpClient = new HttpClinet())
2 {
3     httpClient.BaseAddress = new Uri("http://localhost:8082");
4     await httpClient.GetAsync("Users");  // GET http://localhost:8082/Users
5     await httpClient.PutAsync("User/123", xx);  // PUT http://localhost:8082/User/123
6 }

但是这里呢有个坑,就是传入的Uri是否以“/”结尾或开头,会使得最终请求的地址发生变化。
做个测试:

 1 var baseUri = new Uri("http://localhost:8082/api");
 2 var relativeUri = new Uri("Users", UriKind.Relative);
 3 var requestUri = new Uri(baseUri, relativeUri);
 4 Console.WriteLine(requestUri);  // http://localhost:8082/Users
 5 
 6 var baseUri = new Uri("http://localhost:8082/api/");
 7 var relativeUri = new Uri("Users", UriKind.Relative);
 8 var requestUri= new Uri(baseUri , relativeUri);
 9 Console.WriteLine(requestUri);  // http://localhost:8082/api/Users
10 
11 var baseUri = new Uri("http://localhost:8082/api");
12 var relativeUri = new Uri("/Users", UriKind.Relative);
13 var requestUri= new Uri(baseUri, relativeUri);
14 Console.WriteLine(requestUri);  // http://localhost:8082/Users
15 
16 var baseUri = new Uri("http://localhost:8082/api/");
17 var relativeUri = new Uri("/Users", UriKind.Relative);
18 var requestUri= new Uri(baseUri, relativeUri);
19 Console.WriteLine(requestUri);  // http://localhost:8082/Users

可以看出,只有baseUri以“/”结尾,且relativeUri不以“/”开头,才会得到完整的Uri,其它的都会缺失“api”这部分。
查找官方文档,可以找到相关说明(Uri构造函数):

1、如果relativeUri是绝对地址,那么最终地址采用relativeUri
2、如果baseUri包含相对部分,那么只会保留以“/”结尾的相对部分
3、如果relativeUri以“/”开头,那么会替换掉baseUri中所有的相对部分

按上述条件接着测试:

 1 var baseUri = new Uri("http://localhost:8082/api");
 2 var relativeUri = new Uri("http://localhost:8082/api2");
 3 var requestUri = new Uri(baseUri, relativeUri);
 4 Console.WriteLine(requestUri);  // http://localhost:8082/api2
 5 
 6 var baseUri = new Uri("http://localhost:8082/api/test");
 7 var relativeUri = new Uri("Users", UriKind.Relative);
 8 var requestUri = new Uri(baseUri, relativeUri);
 9 Console.WriteLine(requestUri);  // http://localhost:8082/api/Users
10 
11 var baseUri = new Uri("http://localhost:8082/api/test/");
12 var relativeUri = new Uri("Users", UriKind.Relative);
13 var requestUri = new Uri(baseUri, relativeUri);
14 Console.WriteLine(requestUri);  // http://localhost:8082/api/test/Users
15 
16 var baseUri = new Uri("http://localhost:8082/api/test/");
17 var relativeUri = new Uri("/Users", UriKind.Relative);
18 var requestUri = new Uri(baseUri, relativeUri);
19 Console.WriteLine(requestUri);  // http://localhost:8082/Users
20 
21 var baseUri = new Uri("http://localhost:8082/api/test/");
22 var relativeUri = new Uri("/User/123/", UriKind.Relative);
23 var requestUri = new Uri(baseUri, relativeUri);
24 Console.WriteLine(requestUri);  // http://localhost:8082/User/123/

结果很清晰,最终Uri优先取决relativeUri,其次取决baseUri。

不过,如果仅有baseUri或relativeUri,那还会按“/”来分割吗?继续测试:

 1 var baseUri = new Uri("http://localhost:8082/api/test/");
 2 var relativeUri = new Uri("http://localhost:8082/api2/test");
 3 var requestUri = new Uri(baseUri, relativeUri);
 4 Console.WriteLine(requestUri);  // http://localhost:8082/api2/test
 5 
 6 var baseUri = new Uri("http://localhost:8082/api/test");
 7 var relativeUri = new Uri("/", UriKind.Relative);
 8 var requestUri = new Uri(baseUri, relativeUri);
 9 Console.WriteLine(requestUri);  // http://localhost:8082/
10 
11 var baseUri = new Uri("http://localhost:8082/api/test");
12 var relativeUri = new Uri("", UriKind.Relative);
13 var requestUri = new Uri(baseUri, relativeUri);
14 Console.WriteLine(requestUri);  // http://localhost:8082/api2/test
15 
16 var relativeUri = new Uri("/api/Users", UriKind.Relative);
17 Console.WriteLine(relativeUri);  // /api/Users

所以根据测试结果可以追加2条规则:
1、如果relativeUri是绝对地址,那么完全采用relativeUri,无论是否以“/”结尾
2、如果仅有baseUri或relativeUri,那么不做任何处理

另外,有兴趣的可以反编译System.dll看看Uri对象具体实现。

原文地址:https://www.cnblogs.com/linys2333/p/11025094.html