从绝对名称获取URI/URL的父级名称 C#

21

给定一个绝对URI/URL,我想获取一个不包含末尾部分的URI/URL。例如:给定 http://foo.com/bar/baz.html ,我应该得到 http://foo.com/bar/

我能想到的代码似乎有点冗长,所以我想知道是否有更好的方法。

static string GetParentUriString(Uri uri)
    {            
        StringBuilder parentName = new StringBuilder();

        // Append the scheme: http, ftp etc.
        parentName.Append(uri.Scheme);            

        // Appned the '://' after the http, ftp etc.
        parentName.Append("://");

        // Append the host name www.foo.com
        parentName.Append(uri.Host);

        // Append each segment except the last one. The last one is the
        // leaf and we will ignore it.
        for (int i = 0; i < uri.Segments.Length - 1; i++)
        {
            parentName.Append(uri.Segments[i]);
        }
        return parentName.ToString();
    }

有人会像这样使用该函数:

  static void Main(string[] args)
    {            
        Uri uri = new Uri("http://foo.com/bar/baz.html");
        // Should return http://foo.com/bar/
        string parentName = GetParentUriString(uri);                        
    }

谢谢,Rohit

11个回答

37

你试过这个吗?看起来很简单。

Uri parent = new Uri(uri, "..");

25
略微不正确。按照您现在的方式,只有当uri是目录时才是正确的。如果uri是文件(如原始帖子中所示),那么正确的方法是Uri parent = new Uri(uri, "."); - Nick Babcock

32
这是我能想到的最简短的方法:
static string GetParentUriString(Uri uri)
{
    return uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments.Last().Length);
}

如果你想使用Last()方法,你需要包含System.Linq。


1
是的,但如果URL具有重复字符串,这会导致问题:http://foo.com/bar/baz/bar - Rohit
1
警告:这将忽略查询字符串。 - Brian
@Brian 是正确的,但为了澄清:Martin 的解决方案适用于查询字符串存在的情况,但这被排除在返回值之外。 - rogersillito
不,当查询字符串存在时,它无法很好地工作。调用 GetParentUriString(new Uri("http://foo.com/bar/baz.html?q=val")) 将返回 http://foo.com/bar/baz.ht - Andre Soares
这对于路径形式为C:\sites\041323_KaiTakSportsPark的情况表现不佳,该路径被截断为C:\sites\041323_K此答案,特别是相关评论更简单,并且通用。 - alelom

8

使用内置的uri方法可能有更简单的方法,但这是我对@unknown(雅虎)建议的改进。
在此版本中,您不需要System.Linq,它还处理带有查询字符串的URI:

private static string GetParentUriString(Uri uri)
{
    return uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments[uri.Segments.Length -1].Length - uri.Query.Length);
}

1

我在这里阅读了许多答案,但没有找到一个我喜欢的,因为它们在某些情况下会出现问题。

所以,我正在使用这个:

public Uri GetParentUri(Uri uri) {
    var withoutQuery = new Uri(uri.GetComponents(UriComponents.Scheme |
                                                 UriComponents.UserInfo |
                                                 UriComponents.Host |
                                                 UriComponents.Port |
                                                 UriComponents.Path, UriFormat.UriEscaped));
    var trimmed = new Uri(withoutQuery.AbsoluteUri.TrimEnd('/'));
    var result = new Uri(trimmed, ".");
    return result;
}

注意:它有意删除查询和片段。

1
PapyRef的答案是不正确的,UriPartial.Path包括文件名。
new Uri(uri, ".").ToString()

似乎是所请求的函数最干净/最简单的实现。

我发现它只在资源为文件时有效。如果它是以“/”结尾的URL,它将不会删除最后一段。 - Andre Soares

1

我找到的最短方式:

static Uri GetParent(Uri uri) {
    return new Uri(uri, Path.GetDirectoryName(uri.LocalPath) + "/");
}

1

快速而简单

int pos = uriString.LastIndexOf('/');
if (pos > 0) { uriString = uriString.Substring(0, pos); } 

只是提醒一下…有些情况可能会出错…如果查询字符串中有未编码的URI,这是非常合法的。 - Steve Severance
谢谢你,Steve。对我来说,这证明了一个观点:在处理像URI或文件路径这样的复杂格式时,永远不应该使用裸字符串或正则表达式操作 :) - dbkk

0

获取URL的分段

url="http://localhost:9572/School/Common/Admin/Default.aspx"

Dim name() As String = HttpContext.Current.Request.Url.Segments

now simply using for loop or by index, get parent directory name

code = name(2).Remove(name(2).IndexOf("/"))

这会返回给我 "Common"。


0
new Uri(uri.AbsoluteUri + "/../")

0

我想插一句话; 尽管已经过去了将近10年,但随着云计算的出现,获取父级Uri是一个相当常见(并且在我看来更有价值)的场景,因此结合这里的一些答案,您可以简单地使用(扩展的)Uri语义:

public static Uri Parent(this Uri uri)
{
    return new Uri(uri.AbsoluteUri.Remove(uri.AbsoluteUri.Length - uri.Segments.Last().Length - uri.Query.Length).TrimEnd('/'));
}

var source = new Uri("https://foo.azure.com/bar/source/baz.html?q=1");

var parent = source.Parent();         // https://foo.azure.com/bar/source
var folder = parent.Segments.Last();  // source

我不能说我测试了每种情况,所以建议谨慎。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接