当前位置:  开发笔记 > 编程语言 > 正文

URL.Combine的URL?

如何解决《URL.Combine的URL?》经验,为你挑选了14个好方法。

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

我正在寻找这样的语法:

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

将返回:

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



1> Joel Beckham..:

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类,不幸的是它不会像OP那样表现得像Path.Combine.例如新的Uri(新的Uri("http://test.com/mydirectory/"),"/ helloworld.aspx").ToString()为您提供"http://test.com/helloworld.aspx"; 如果我们想要一个Path.Combine样式结果,这将是不正确的.
这都是斜线.如果相对路径部分以斜杠开头,那么它的行为与您所描述的相同.但是,如果你留下斜线,那么它会按你期望的方式工作(注意第二个参数上缺少的斜线):new Uri(new Uri("http://test.com/mydirectory/")," helloworld.aspx").ToString()导致"http://test.com/mydirectory/helloworld.aspx".Path.Combine表现相似.如果相对路径参数以斜杠开头,则它仅返回相对路径并且不合并它们.
如果您的baseUri恰好是"test.com/mydirectory/mysubdirectory",那么结果将是"test.com/mydirectory/helloworld.aspx"而不是"test.com/mydirectory/mysubdirectory/helloworld.aspx".细微差别是第一个参数缺少尾部斜杠.我全都使用现有的框架方法,如果我必须在那里使用尾部斜杠那么我认为做partUrl1 + partUrl2的气味要少得多 - 我可能已经在追逐那个尾随斜线了很长一段时间为了不做字符串连接.
我想要一个URI组合方法的唯一原因是我不必检查尾部斜杠.如果您的应用程序位于根目录,则Request.ApplicationPath为"/",如果不是,则为"/ foo".
我-1这个答案,因为这不能解决问题.当你想要组合url时,就像你想使用Path.Combine一样,你不想关心尾随/.有了这个,你必须要关心.我更喜欢上面的Brian MacKay或mdsharpe解决方案
作为尽可能多地使用已经构建的代码的粉丝,我想知道为什么没有人建议这个,直到我发现你的答案.这是IMO的最佳答案.
当第一个URI不是域的根时,此答案不会传递货物.耻辱.
-1`new Uri(new Uri("test.com/mydirectory"),"helloworld.aspx")`返回`test.com/helloworld.aspx`,这不是任何人想要的.
如果您在虚拟路径中而不是在网站的根目录中部署应用程序,则此代码可能会出错.如果您的基本网址是my.website.com/virtualdir,相对pathe将是catalog/page.html,这将返回my.website.com/catalog/page.html,错过了vitrualdir
我曾经是这种方法的忠实粉丝,并且无处不在地使用它,当我发现"Uri"类的URL解码查询字符串参数的讨厌习惯时,它让我很难受.更糟糕的是,这是设计上的.请参见http://stackoverflow.com/a/7307950.尽管我讨厌它,但我现在手动完成所有URL连接.至少它不会搞砸我的返回者.

2> Matthew Shar..:

这可能是一个非常简单的解决方案:

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


+1:虽然这不处理相对风格的路径(../../whatever.html),但我喜欢这个简单的路径.我还会为'\'字符添加修剪.
请参阅我的回答,了解更完整的版本.

3> Ryan Cook..:

你用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


+1:这很好,虽然我对输出参数有一个不合理的问题.;)
这个答案遇到了与[Joel](http://stackoverflow.com/a/1527643/56145)相同的问题:加入`test.com/mydirectory /`和`/ helloworld.aspx`将导致`test.com/ helloworld.aspx`这看似不是你想要的.
@Brian:如果有帮助,所有TryXXX方法(`int.TryParse`,`DateTime.TryParseExact`)都有这个输出参数,以便在if语句中更容易使用它们.顺便说一下,你不必像Ryan在这个例子中那样初始化变量.
嗨,这次失败了:if(Uri.TryCreate(new Uri("http:// localhost/MyService /"),"/ Event/SomeMethod?abc = 123",out result)){Console.WriteLine(result) ; 它显示我的结果为:http:// localhost/Event/SomeMethod?abc = 123注意:"http://"在这里由stackoverflow从基础Uri替换
@FaisalMq这是正确的行为,因为您传递了根相对第二个参数.如果你遗漏了第二个参数的前导/上限,你就得到了预期的结果.

4> Ales Potocni..:

这里已经有了一些很棒的答案.基于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


这个解决方案使得编写与Path.Combine()非常相似的UriUtils.Combine("base url","part1","part2",...)静态方法变得微不足道.太好了!

5> Brian MacKay..:

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中:

 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


谈论细节:如果参数是'Nothing`,强制的`ArgumentNullException("url1")`怎么办?对不起,只是挑剔;-).请注意,反斜杠在URI中无关(如果它在那里,则不应该进行修剪),因此您可以从TrimXXX中删除它.
你可以使用params string []并递归地连接它们以允许超过2种组合
我当然希望这是在基类库中像Path.Combine.

6> MiFreidgeim ..:

上面有一个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> Install-Package Flurl.Http

或者获取没有HTTP功能的独立URL构建器:

PM> Install-Package Flurl


嗯,这个问题获得了大量的流量,1000+ upvotes的答案实际上并不适用于所有情况.多年以后,我实际上使用Flurl,所以我接受这个.它似乎适用于我遇到的所有情况.如果人们不想依赖,我发布了一个也很好的答案.

7> 小智..:

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

基于这个假设,我将提出这个解决方案作为对你的问题的最恰当的回答:"Path.Combine很方便,URL的框架中是否有类似的功能?"

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

有一点需要注意:我认为这仅适用于相对于您网站的网址(也就是说,您无法使用它来生成指向其他网站的链接.例如,var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");).


警告是正确的,它不能用绝对的uris工作,结果总是相对于根.但它有一个额外的好处,它处理波浪号,就像"〜/".这使它成为`Server.MapPath`和组合的快捷方式.

8> Mike Fuchs..:

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



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


`path.Replace(Path.DirectorySeparatorChar,'/');`
@SliverNinja这不正确*这个字段的值是UNIX上的反斜杠('\'),在Windows和Macintosh操作系统上是斜杠('/').*在Linux系统上使用Mono时,你会得到错误的分隔符.
`path.Replace(Path.DirectorySeparatorChar,Path.AltDirectorySeparatorChar)`
在目录分隔符上调用的所有yall都忘记了字符串可能来自与现在不同的操作系统.只需用正斜杠替换反斜杠就可以了.

10> 小智..:

我只是把一个小的扩展方法放在一起:

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");



11> mtazva..:

一个很好的例子,Ryan,以这个功能的链接结束.做得好.

一个建议Brian:如果将此代码包装在函数中,您可能希望在TryCreate调用之前使用UriBuilder来包装基本URL.

否则,基本URL必须包含该方案(UriBuilder将采用http://).只是一个想法:

public string CombineUrl(string baseUrl, string relativeUrl) {
    UriBuilder baseUri = new UriBuilder(baseUrl);
    Uri newUri;

    if (Uri.TryCreate(baseUri.Uri, relativeUrl, out newUri))
        return newUri.ToString();
    else
        throw new ArgumentException("Unable to combine specified url values");
}



12> 小智..:

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

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



13> Believe2014..:

组合URL的多个部分可能有点棘手.您可以使用双参数构造函数Uri(baseUri, relativeUri),也可以使用Uri.TryCreate()实用程序函数.

在这两种情况下,你可能最终会返回一个不正确的结果,因为这些方法不断截断相对部分关闭的第一个参数baseUri,即从像http://google.com/some/thinghttp://google.com.

为了能够将多个部分组合成最终的URL,您可以复制以下两个函数:

    public static string Combine(params string[] parts)
    {
        if (parts == null || parts.Length == 0) return string.Empty;

        var urlBuilder = new StringBuilder();
        foreach (var part in parts)
        {
            var tempUrl = tryCreateRelativeOrAbsolute(part);
            urlBuilder.Append(tempUrl);
        }
        return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToString());
    }

    private static string tryCreateRelativeOrAbsolute(string s)
    {
        System.Uri uri;
        System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri);
        string tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToString());
        return tempUrl;
    }

可以在https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs上找到用于演示用法的单元测试的完整代码.

我有单元测试来涵盖三种最常见的情况:

在此输入图像描述


对我来说看起来不错。尽管您可以用foreach循环替换I循环以提高清晰度。

14> javajavajava..:

我发现UriBuilder这种事情非常好用:

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

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

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有