[C#] Path.Combine para URLs?


Answers

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

Regresará:

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

Question

Path.Combine es útil, pero ¿existe una función similar en el marco de .NET para las URLs ?

Estoy buscando una sintaxis como esta:

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

que regresaría:

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




Ambos funcionan

  Uri final = new Uri(Regex.Replace(baseUrl + "/" + relativePath, "(?<!http:)/{2,}", "/"));

O

  Uri final =new Uri(string.Format("{0}/{1}", baseUrl.ToString().TrimEnd('/'), relativePath.ToString().TrimStart('/')));

es decir

Si

baseUrl = " http://tesrurl.test.com/Int18 "

y

relativePath = "To_Folder"

salida = http://tesrurl.test.com/Int18/To_Folder

Algunos errores aparecerán para el código a continuación

 // if you use below code, some issues will be there in final uri
 Uri final= new Uri(baseUrl ,relativePath );



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



Ya hay algunas buenas respuestas aquí. En función de la sugerencia de mdsharpe, este es un método de extensión que se puede usar fácilmente cuando desee tratar instancias de 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('/'))));
    }
}

Y ejemplo de uso:

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

Esto producirá http://example.com/subpath/part1/part2




¿Por qué no solo usa lo siguiente?

System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")



En función de la URLs muestra que proporcionó, supongo que desea combinar las URL relacionadas con su sitio.

Con base en esta suposición, propondré esta solución como la respuesta más adecuada a su pregunta que fue: "Path.Combine es útil, ¿hay alguna función similar en el marco de las URL?"

Como existe una función similar en el marco de las URL, propongo que el método correcto es "VirtualPathUtility.Combine". Aquí está el enlace de referencia de MSDN: Método VirtualPathUtility.Combine

Hay una advertencia: creo que esto solo funciona para las URL relativas a su sitio (es decir, no puede usarlo para generar enlaces a otro sitio web. Por ejemplo, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets"); ).




Sé que llego tarde a la fiesta, pero creé esta función que hará su vida más fácil

    /// <summary>
    /// the ultimate Path combiner of all time
    /// </summary>
    /// <param name="IsURL">
    /// true - if the paths are internet urls,false - if the paths are local urls,this is very important as this will be used to decide which separator will be used
    /// </param>
    /// <param name="IsRelative">just adds the separator at the beginning</param>
    /// <param name="IsFixInternal">fix the paths from within (by removing duplicate separators and correcting the separators)</param>
    /// <param name="parts">the paths to combine</param>
    /// <returns>the combined path</returns>
    public static string PathCombine(bool IsURL , bool IsRelative , bool IsFixInternal , params string[] parts)
    {
        if (parts == null || parts.Length == 0) return string.Empty;
        char separator = IsURL ? '/' : '\\';

        if (parts.Length == 1 && IsFixInternal)
        {

            string validsingle;
            if (IsURL)
            {
                validsingle = parts[0].Replace('\\' , '/');
            }
            else
            {
                validsingle = parts[0].Replace('/' , '\\');
            }
            validsingle = validsingle.Trim(separator);
            return (IsRelative ? separator.ToString() : string.Empty) + validsingle;
        }

        string final = parts
            .Aggregate
            (
            (string first , string second) =>
            {
                string validfirst;
                string validsecond;
                if (IsURL)
                {
                    validfirst = first.Replace('\\' , '/');
                    validsecond = second.Replace('\\' , '/');
                }
                else
                {
                    validfirst = first.Replace('/' , '\\');
                    validsecond = second.Replace('/' , '\\');
                }
                var prefix = string.Empty;
                if (IsFixInternal)
                {
                    if (IsURL)
                    {
                        if (validfirst.Contains("://"))
                        {
                            var tofix = validfirst.Substring(validfirst.IndexOf("://") + 3);
                            prefix = validfirst.Replace(tofix , string.Empty).TrimStart(separator);

                            var tofixlist = tofix.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);

                            validfirst = separator + string.Join(separator.ToString() , tofixlist);
                        }
                        else
                        {
                            var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
                            validfirst = string.Join(separator.ToString() , firstlist);
                        }

                        var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
                        validsecond = string.Join(separator.ToString() , secondlist);
                    }
                    else
                    {
                        var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
                        var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);

                        validfirst = string.Join(separator.ToString() , firstlist);
                        validsecond = string.Join(separator.ToString() , secondlist);
                    }

                }
                return prefix + validfirst.Trim(separator) + separator + validsecond.Trim(separator);
            }
            );
        return (IsRelative ? separator.ToString() : string.Empty) + final;
    }

funciona tanto para URL como para rutas normales

Uso:

    //fixes internal paths
    Console.WriteLine(PathCombine(true , true , true , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\"));
    //result : /folder 1/folder2/folder3/somefile.ext


    //doesn't fix internal paths
    Console.WriteLine(PathCombine(true , true , false , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\"));
    //result : /folder 1//////////folder2////folder3/somefile.ext


    //don't worry about url prefixes when fixing internal paths
    Console.WriteLine(PathCombine(true , false , true , @"/\/\/https:/\/\/\lul.com\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\"));
    //result : https://lul.com/folder2/folder3/somefile.ext


    Console.WriteLine(PathCombine(false , true , true , @"../../../\\..\...\./../somepath" , @"anotherpath"));
    //result : \..\..\..\..\...\.\..\somepath\anotherpath



Aquí está el método de Microsoft (OfficeDev PnP) 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);
    }

Fuente: UrlUtility.Combine




Bueno, simplemente concateno dos cadenas y uso expresiones regulares para hacer la parte de limpieza.

    public class UriTool
    {
        public static Uri Join(string path1, string path2)
        {
            string url = path1 + "/" + path2;
            url = Regex.Replace(url, "(?<!http:)/{2,}", "/");

            return new Uri(url);
        }
    }

Entonces, puedes usar esto:

    string path1 = "http://someaddress.com/something/";
    string path2 = "/another/address.html";
    Uri joinedUri = UriTool.Join(path1, path2);

    // joinedUri.ToString() returns "http://someaddress.com/something/another/address.html"

Espero que pueda ser útil para alguien!




¿Qué tal esto?

 public static class WebPath
    {
        public static string Combine(params string[] args)
        {
            var prefixAdjusted = args.Select(x => x.StartsWith("/") && !x.StartsWith("http") ? x.Substring(1) : x);
            return string.Join("/", prefixAdjusted);
        }
    }



Ejemplo ingenioso, Ryan, para terminar con un enlace a la función. Bien hecho.

Una recomendación Brian: si ajusta este código en una función, es posible que desee utilizar un UriBuilder para ajustar la URL base antes de la llamada TryCreate.

De lo contrario, la URL base DEBE incluir el esquema (donde el UriBuilder asumirá http: //). Solo un pensamiento:

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



Sé que esto ha sido respondido, pero una manera fácil de combinarlos y garantizar que siempre sea correcto es ...

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



We use the following simple helper method to join arbitrary number of URL parts together:

public static string JoinUrlParts(params string[] urlParts)
{
    return string.Join("/", urlParts.Where(up => !string.IsNullOrEmpty(up)).ToList().Select(up => up.Trim('/')).ToArray());
}

Note, that it doesn't support '../../something/page.htm'-style relative URL-s!




    private Uri UriCombine(string path1, string path2, string path3 = "", string path4 = "")
    {
        string path = System.IO.Path.Combine(path1, path2.TrimStart('\\', '/'), path3.TrimStart('\\', '/'), path4.TrimStart('\\', '/'));
        string url = path.Replace('\\','/');
        return new Uri(url);
    }

Tiene los beneficios de comportarse exactamente como Path.Combine




I have to point out that Path.Combine appears to work for this also directly atleast on .NET4