URL 的 Path.Combine 吗?

Path.Combine很方便,但是. NET 框架中是否有用于URL的类似功能?

我正在寻找这样的语法:

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

这将返回:

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

答案

Uri具有应为您执行此操作的构造函数: new Uri(Uri baseUri, string relativeUri)

这是一个例子:

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

编辑注意:请注意,此方法无法正常工作。在某些情况下,它可以削减 baseUri 的一部分。查看评论和其他答案。

您使用Uri.TryCreate( ... )

Uri result = null;

if (Uri.TryCreate(new Uri("http://msdn.microsoft.com/en-us/library/"), "/en-us/library/system.uri.trycreate.aspx", out result))
{
    Console.WriteLine(result);
}

将返回:

http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx

这可能是一个适当的简单解决方案:

public static string Combine(string uri1, string uri2)
{
    uri1 = uri1.TrimEnd('/');
    uri2 = uri2.TrimStart('/');
    return string.Format("{0}/{1}", uri1, uri2);
}

这里已经有了一些很好的答案。根据 mdsharpe 的建议,这是一种扩展方法,当您要处理 Uri 实例时,可以轻松使用它:

using System;
using System.Linq;

public static class UriExtensions
{
    public static Uri Append(this Uri uri, params string[] paths)
    {
        return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => string.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/'))));
    }
}

和用法示例:

var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri;

这将产生http://example.com/subpath/part1/part2

瑞安 · 库克(Ryan Cook)的答案接近于我的追求,可能更适合其他开发人员。但是,它在字符串的开头添加了 http://,并且总的来说,格式化要比后面的要多。

另外,对于我的用例,解决相对路径也不重要。

mdsharp 的答案还包含一个好主意,尽管实际的实现需要更多细节才能完成。这是一个充实的尝试(我正在生产中使用它):

C#

public string UrlCombine(string url1, string url2)
{
    if (url1.Length == 0) {
        return url2;
    }

    if (url2.Length == 0) {
        return url1;
    }

    url1 = url1.TrimEnd('/', '\\');
    url2 = url2.TrimStart('/', '\\');

    return string.Format("{0}/{1}", url1, url2);
}

VB.NET

Public Function UrlCombine(ByVal url1 As String, ByVal url2 As String) As String
    If url1.Length = 0 Then
        Return url2
    End If

    If url2.Length = 0 Then
        Return url1
    End If

    url1 = url1.TrimEnd("/"c, "\"c)
    url2 = url2.TrimStart("/"c, "\"c)

    Return String.Format("{0}/{1}", url1, url2)
End Function

此代码通过了以下测试,恰好在 VB 中:

<TestMethod()> Public Sub UrlCombineTest()
    Dim target As StringHelpers = New StringHelpers()

    Assert.IsTrue(target.UrlCombine("test1", "test2") = "test1/test2")
    Assert.IsTrue(target.UrlCombine("test1/", "test2") = "test1/test2")
    Assert.IsTrue(target.UrlCombine("test1", "/test2") = "test1/test2")
    Assert.IsTrue(target.UrlCombine("test1/", "/test2") = "test1/test2")
    Assert.IsTrue(target.UrlCombine("/test1/", "/test2/") = "/test1/test2/")
    Assert.IsTrue(target.UrlCombine("", "/test2/") = "/test2/")
    Assert.IsTrue(target.UrlCombine("/test1/", "") = "/test1/")
End Sub

上面有一个 Todd Menier 的评论Flurl包含一个 Url.Combine。

更多细节:

Url.Combine 本质上是 URL 的 Path.Combine,确保部分之间只有一个分隔符:

var url = Url.Combine(
    "http://foo.com/",
    "/too/", "/many/", "/slashes/",
    "too", "few?",
    "x=1", "y=2"
// result: "http://www.foo.com/too/many/slashes/too/few?x=1&y=2"

在 NuGet 上获取Flurl.Http

PM > 安装包 Flurl.Http

获取不具有 HTTP 功能的独立 URL 构建器

PM > 安装包 Flurl

根据您提供的示例URL ,我将假设您要组合相对于您的网站的 URL。

基于此假设,我将提出此解决方案作为对您的问题的最适当答复:“ Path.Combine 很方便,URL 框架中是否有类似的功能 ?”

由于 URL 框架中存在类似的功能 ,因此我建议正确的方法是:“VirtualPathUtility.Combine” 方法。这是 MSDN 参考链接: VirtualPathUtility.Combine 方法

有一个警告:我相信这仅适用于相对于您的网站的 URL(也就是说,您不能使用它来生成指向另一个网站的链接。例如, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets"); )。

Path.Combine 对我不起作用,因为可能会有类似 “|” 的字符在 QueryString 参数中,因此在 URL 中,这将导致 ArgumentException。

我首先尝试了新的Uri(Uri baseUri, string relativeUri)方法,但由于诸如http://www.mediawiki.org/wiki/Special:SpecialPages之类的 URI 而失败了:

new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")

将导致 Special:SpecialPages,因为Special后面的冒号表示一个方案。

因此,我最终不得不采取 mdsharpe / Brian MacKays 的路线,并对其进行了进一步开发,以使用多个 URI 部分:

public static string CombineUri(params string[] uriParts)
{
    string uri = string.Empty;
    if (uriParts != null && uriParts.Length > 0)
    {
        char[] trims = new char[] { '\\', '/' };
        uri = (uriParts[0] ?? string.Empty).TrimEnd(trims);
        for (int i = 1; i < uriParts.Length; i++)
        {
            uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims));
        }
    }
    return uri;
}

用法: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")

Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")

我只是整理了一个小的扩展方法:

public static string UriCombine (this string val, string append)
        {
            if (String.IsNullOrEmpty(val)) return append;
            if (String.IsNullOrEmpty(append)) return val;
            return val.TrimEnd('/') + "/" + append.TrimStart('/');
        }

可以这样使用:

"www.example.com/".UriCombine("/images").UriCombine("first.jpeg");