Path.Combine for URLs?

前端 未结 30 2119
不思量自难忘°
不思量自难忘° 2020-11-22 14:28

Path.Combine is handy, but is there a similar function in the .NET framework for URLs?

I\'m looking for syntax like this:

Url.Combine(\"http://MyUrl.         


        
相关标签:
30条回答
  • 2020-11-22 15:09

    Rules while combining URLs with a URI

    To avoid strange behaviour there's one rule to follow:

    • The path (directory) must end with '/'. If the path ends without '/', the last part is treated like a file-name, and it'll be concatenated when trying to combine with the next URL part.
    • There's one exception: the base URL address (without directory info) needs not to end with '/'
    • the path part must not start with '/'. If it start with '/', every existing relative information from URL is dropped...adding a string.Empty part path will remove the relative directory from the URL too!

    If you follow rules above, you can combine URLs with the code below. Depending on your situation, you can add multiple 'directory' parts to the 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();
            });
    
    0 讨论(0)
  • 2020-11-22 15:09

    Here is my approach and I will use it for myself too:

    public static string UrlCombine(string part1, string part2)
    {
        string newPart1 = string.Empty;
        string newPart2 = string.Empty;
        string seperator = "/";
    
        // If either part1 or part 2 is empty,
        // we don't need to combine with seperator
        if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2))
        {
            seperator = string.Empty;
        }
    
        // If part1 is not empty,
        // remove '/' at last
        if (!string.IsNullOrEmpty(part1))
        {
            newPart1 = part1.TrimEnd('/');
        }
    
        // If part2 is not empty,
        // remove '/' at first
        if (!string.IsNullOrEmpty(part2))
        {
            newPart2 = part2.TrimStart('/');
        }
    
        // Now finally combine
        return string.Format("{0}{1}{2}", newPart1, seperator, newPart2);
    }
    
    0 讨论(0)
  • 2020-11-22 15:10

    Here's Microsoft's (OfficeDev PnP) method UrlUtility.Combine:

        const char PATH_DELIMITER = '/';
    
        /// <summary>
        /// Combines a path and a relative path.
        /// </summary>
        /// <param name="path"></param>
        /// <param name="relative"></param>
        /// <returns></returns>
        public static string Combine(string path, string relative) 
        {
            if(relative == null)
                relative = String.Empty;
    
            if(path == null)
                path = String.Empty;
    
            if(relative.Length == 0 && path.Length == 0)
                return String.Empty;
    
            if(relative.Length == 0)
                return path;
    
            if(path.Length == 0)
                return relative;
    
            path = path.Replace('\\', PATH_DELIMITER);
            relative = relative.Replace('\\', PATH_DELIMITER);
    
            return path.TrimEnd(PATH_DELIMITER) + PATH_DELIMITER + relative.TrimStart(PATH_DELIMITER);
        }
    

    Source: GitHub

    0 讨论(0)
  • 2020-11-22 15:10

    I think this should give you more flexibility as you can deal with as many path segments as you want:

    public static string UrlCombine(this string baseUrl, params string[] segments)
    => string.Join("/", new[] { baseUrl.TrimEnd('/') }.Concat(segments.Select(s => s.Trim('/'))));
    
    0 讨论(0)
  • 2020-11-22 15:11

    Ryan Cook's answer is close to what I'm after and may be more appropriate for other developers. However, it adds http:// to the beginning of the string and in general it does a bit more formatting than I'm after.

    Also, for my use cases, resolving relative paths is not important.

    mdsharp's answer also contains the seed of a good idea, although that actual implementation needed a few more details to be complete. This is an attempt to flesh it out (and I'm using this in production):

    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
    

    This code passes the following test, which happens to be in 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
    
    0 讨论(0)
  • 2020-11-22 15:11

    Witty example, Ryan, to end with a link to the function. Well done.

    One recommendation Brian: if you wrap this code in a function, you may want to use a UriBuilder to wrap the base URL prior to the TryCreate call.

    Otherwise, the base URL MUST include the scheme (where the UriBuilder will assume http://). Just a thought:

    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");
    }
    
    0 讨论(0)
提交回复
热议问题