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

我正在寻找这样的语法:

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

这将返回:

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


当前回答

上面有托德·梅尼尔(Todd Menier)的评论,Flurl包括一个Url.Combine。

更多详情:

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

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

在NuGet上获取Flurl.Http:

PM>安装包Flurl.Http

或者获取没有HTTP功能的独立URL生成器:

PM>安装程序包Flurl

其他回答

这里已经有了一些很好的答案。根据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

如果您希望使用字符串而不是Uris,那么以下操作也会产生相同的结果,只需根据您的需要进行调整即可:

public string JoinUriSegments(string uri, params string[] segments)
{
    if (string.IsNullOrWhiteSpace(uri))
        return null;

    if (segments == null || segments.Length == 0)
        return uri;

    return segments.Aggregate(uri, (current, segment) => $"{current.TrimEnd('/')}/{segment.TrimStart('/')}");
}

var uri = JoinUriSegements("http://example.com/subpath/", "/part1/", "part2");

您使用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

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

Path.Combine对我不起作用,因为QueryString参数中可能有“|”这样的字符,因此URL也会出现ArgumentException。

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

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“)

组合它们并确保始终正确的一种简单方法是:

string.Format("{0}/{1}", Url1.Trim('/'), Url2);