Path.Combine很方便,但是.NET框架中是否有类似的URL函数?

我正在寻找这样的语法:

Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")

这将返回:

"http://MyUrl.com/Images/Image.jpg"


当前回答

我们使用以下简单的助手方法将任意数量的URL部分连接在一起:

public static string JoinUrlParts(params string[] urlParts)
{
    return string.Join("/", urlParts.Where(up => !string.IsNullOrEmpty(up)).ToList().Select(up => up.Trim('/')).ToArray());
}

注意,它不支持'..//something/page.htm'样式的相对URL!

其他回答

将URL与URI组合时的规则

为了避免奇怪的行为,需要遵循一条规则:

路径(目录)必须以“/”结尾。如果路径结尾不带“/”,则最后一部分将被视为文件名,并且在尝试与下一个URL部分组合时将被连接。有一个例外:基本URL地址(没有目录信息)不需要以“/”结尾路径部分不能以“/”开头。如果它以“/”开头,则URL中的所有现有相关信息都将被删除。。。添加字符串。空的部分路径也会从URL中删除相对目录!

如果您遵循上面的规则,您可以将URL与下面的代码组合。根据您的情况,您可以向URL添加多个“目录”部分。。。

        var pathParts = new string[] { destinationBaseUrl, destinationFolderUrl, fileName };

        var destination = pathParts.Aggregate((left, right) =>
        {
            if (string.IsNullOrWhiteSpace(right))
                return left;

            return new Uri(new Uri(left), right).ToString();
        });

Uri有一个构造函数可以为您执行此操作:new Uri(Uri baseUri,string relativeUri)

下面是一个示例:

Uri baseUri = new Uri("http://www.contoso.com");
Uri myUri = new Uri(baseUri, "catalog/shownew.htm");

编辑注意:小心,这种方法并不能像预期的那样工作。在某些情况下,它可以剪切baseUri的一部分。查看评论和其他答案。

所以我有另一种方法,类似于使用UriBuilder的每个人。

我不想拆分我的BaseUrl(它可以包含路径的一部分,例如。http://mybaseurl.com/dev/)正如javajavajavajava所做的那样。

下面的代码片段显示了代码+测试。

注意:此解决方案降低了主机并附加了一个端口。如果不需要这样做,可以通过例如利用UriBuilder的Uri属性来编写字符串表示。

  public class Tests
  {
         public static string CombineUrl (string baseUrl, string path)
         {
           var uriBuilder = new UriBuilder (baseUrl);
           uriBuilder.Path = Path.Combine (uriBuilder.Path, path);
           return uriBuilder.ToString();
         }

         [TestCase("http://MyUrl.com/", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")]
         [TestCase("http://MyUrl.com/basePath", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")]
         [TestCase("http://MyUrl.com/basePath", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")]
         [TestCase("http://MyUrl.com/basePath/", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")]
         public void Test1 (string baseUrl, string path, string expected)
         {
           var result = CombineUrl (baseUrl, path);

           Assert.That (result, Is.EqualTo (expected));
         }
  }

在Windows 10上使用.NET Core 2.1进行测试。

为什么这样做?

尽管Path.Combine将返回反斜杠(至少在Windows上),但UriBuilder在路径设置器中处理这种情况。

摘自https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/src/System/UriBuilder.cs(注意调用字符串。替换)

[AllowNull]
public string Path
{
      get
      {
          return _path;
      }
      set
      {
          if ((value == null) || (value.Length == 0))
          {
              value = "/";
          }
          _path = Uri.InternalEscapeString(value.Replace('\\', '/'));
          _changed = true;
      }
 }

这是最好的方法吗?

当然,这个解决方案非常自我描述(至少在我看来)。但是,您依赖的是.NETAPI中的未记录(至少我在快速谷歌搜索中没有发现任何内容)“功能”。这可能会随着将来的版本而改变,因此请将方法与测试结合起来。

中有测试https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/tests/FunctionalTests/UriBuilderTests.cs(Path_Get_Set),用于检查\是否正确转换。

附带说明:如果Uri将用于System.Uri构造函数,则也可以直接使用UriBuilder.Uri属性。

我认为这应该给你更多的灵活性,因为你可以处理任意多的路径段:

public static string UrlCombine(this string baseUrl, params string[] segments)
=> string.Join("/", new[] { baseUrl.TrimEnd('/') }.Concat(segments.Select(s => s.Trim('/'))));

我发现UriBuilder在这种情况下工作得很好:

UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;

有关更多构造函数和文档,请参阅UriBuilder类-MSDN。