Path.Combine для URL?

1079

Path.Combine удобен, но есть ли аналогичная функция в платформе .NET для URL-адрес?

Я ищу синтаксис вот так:

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

который вернется:

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

  • 12
    Flurl включает метод Url.Combine который делает именно это.
  • 1
    На самом деле // обрабатывается маршрутизацией веб-сайта или сервера, а не браузером. Он отправит то, что вы положили в адресную строку. Вот почему у нас возникают проблемы, когда мы набираем htp: // вместо http: // Таким образом, // может вызвать серьезные проблемы на некоторых сайтах. Я пишу .dll для сканера, который обрабатывает определенный веб-сайт, который выбрасывает 404, если у вас есть // в URL.
Теги:
url
path

33 ответа

7
Лучший ответ

Выше есть комментарий Тодда Меньера, что Flurl включает Url.Combine.

Больше деталей:

Url.Combine - это, по сути, Path.Combine для URL, обеспечивающий один и только один символ-разделитель между частями:

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" 

Получить Flurl.Http на NuGet:

PM> Install-Package Flurl.Http

Или получите автономный конструктор URL без функций HTTP:

PM> Установить-пакет Flurl

  • 3
    Ну, этот вопрос получает много трафика, и ответ с более чем 1000 голосов не работает на самом деле во всех случаях. Спустя годы я на самом деле использую Flurl для этого, поэтому я принимаю этот. Кажется, работает во всех случаях, с которыми я столкнулся. Если люди не хотят получать зависимость, я разместил ответ, который также отлично работает.
  • 0
    и если вы не используете Flurl и Flurl облегченную версию, github.com/jean-lourenco/UrlCombine
993

Uri есть конструктор, который должен сделать это за вас: new Uri(Uri baseUri, string relativeUri)

Вот пример:

Uri baseUri = new Uri("http://www.contoso.com");
Uri myUri = new Uri(baseUri, "catalog/shownew.htm");

Примечание редактора: будьте осторожны, этот метод не работает должным образом. В некоторых случаях он может вырезать часть baseUri. Смотрите комментарии и другие ответы.

  • 7
    Как любитель использовать как можно больше уже созданного кода, мне было интересно, почему никто еще не предложил этого, пока я не заметил ваш ответ. Это, IMO, лучший ответ.
  • 334
    Мне нравится использование класса Uri, к сожалению, он не будет вести себя как Path.Combine, как спросил ОП. Например, новый Uri (новый Uri (" test.com/mydirectory/" ), "/helloworld.aspx"). ToString () дает вам " test.com/helloworld.aspx "; что было бы неправильно, если бы мы хотели получить результат в стиле Path.Combine.
Показать ещё 23 комментария
141

Вы используете 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

  • 47
    +1: это хорошо, хотя у меня иррациональная проблема с выходным параметром. ;)
  • 1
    Это гораздо лучший подход, так как он также будет работать для путей вида "../../something.html"
Показать ещё 6 комментариев
123

Это может быть достаточно простым решением:

public static string Combine(string uri1, string uri2)
{
    uri1 = uri1.TrimEnd('/');
    uri2 = uri2.TrimStart('/');
    return string.Format("{0}/{1}", uri1, uri2);
}
  • 7
    +1: хотя это не обрабатывает пути относительного стиля (../../whwhat.html), мне нравится этот для его простоты. Я бы также добавил обрезки для символа '\'.
  • 3
    Смотрите мой ответ для более полной версии этого.
110

Здесь уже есть отличные ответы. На основе предложения 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

  • 2
    Это решение упрощает написание статического метода UriUtils.Combine ("base url", "part1", "part2", ...), который очень похож на Path.Combine (). Ницца!
  • 0
    Для поддержки относительных URI мне пришлось использовать ToString () вместо AbsoluteUri и UriKind.AbsoluteOrRelative в конструкторе Uri.
Показать ещё 3 комментария
81

Ответ Райана Кука близок к тому, что мне нужно, и может быть более подходящим для других разработчиков. Тем не менее, он добавляет http://в начало строки и в целом он делает немного больше форматирования, чем я после.

Кроме того, для моих случаев использования определение относительных путей не важно.

Ответ mdsharp также содержит в себе идею хорошей идеи, хотя для ее фактической реализации потребовалось еще несколько подробностей. Это попытка уточнить это (и я использую это в производстве):

С#

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
  • 4
    Говоря о деталях: как насчет обязательного ArgumentNullException("url1") если аргумент Nothing ? Извините, просто привередливый ;-). Обратите внимание, что обратный слеш не имеет ничего общего с URI (и, если он есть, его не следует обрезать), так что вы можете удалить его из TrimXXX.
  • 4
    Вы можете использовать params string [] и рекурсивно объединять их, чтобы разрешить более 2 комбинаций
Показать ещё 10 комментариев
31

Исходя из предоставленного вами примера URL, я предполагаю, что вы хотите объединить URL, относящиеся к вашему сайту.

Исходя из этого предположения, я предложу это решение как наиболее подходящий ответ на ваш вопрос: "Path.Combine удобен, есть ли подобная функция в структуре для URL-адресов?"

Поскольку в структуре для URL-адресов есть аналогичная функция, я предлагаю правильный метод: "VirtualPathUtility.Combine". Вот ссылка на MSDN: VirtualPathUtility.Combine Метод

Есть одно предостережение: я считаю, что это работает только для URL, относящихся к вашему сайту (то есть вы не можете использовать его для создания ссылок на другой веб-сайт. Например, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");).

  • 0
    +1, потому что это близко к тому, что я ищу, хотя было бы идеально, если бы это работало для любого старого URL. Я удвою это получится намного элегантнее, чем предложено mdsharpe.
  • 2
    Предостережение правильное, оно не может работать с абсолютным URIS, и результат всегда является относительным от корня. Но у него есть дополнительное преимущество: он обрабатывает тильду, как и «~ /». Это делает его ярлыком для Server.MapPath и объединения.
29

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.Count() > 0)
    {
        char[] trims = new char[] { '\\', '/' };
        uri = (uriParts[0] ?? string.Empty).TrimEnd(trims);
        for (int i = 1; i < uriParts.Count(); 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")

  • 1
    +1: Теперь мы говорим ... Я собираюсь попробовать это. Это может даже оказаться новым принятым ответом. После попытки нового метода Uri () он мне действительно не нравится. Слишком привередливый.
  • 0
    Это именно то, что мне было нужно! Не был фанатом необходимости заботиться о том, где я ставлю косые черты и т.д ...
Показать ещё 1 комментарий
22
Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")
  • 7
    path.Replace(Path.DirectorySeparatorChar, '/');
  • 4
    path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
Показать ещё 4 комментария
15

Я просто собрал небольшой метод расширения:

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

Остроумный пример, Райан, чтобы закончить со ссылкой на функцию. Молодцы.

Одна рекомендация Брайан: если вы закроете этот код в функции, вы можете использовать UriBuilder для обвязывания базового URL до вызова TryCreate.

В противном случае базовый 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");
}
8

Объединение нескольких частей URL может быть немного сложнее. Вы можете использовать двухпараметрический конструктор Uri(baseUri, relativeUri) или служебную функцию Uri.TryCreate().

В любом случае вы можете в итоге вернуть неверный результат, потому что эти методы продолжают baseUri относительные части из первого параметра baseUri, то есть из чего-то вроде http://google.com/some/thing в http://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.

У меня есть модульные тесты, чтобы охватить три наиболее распространенных случая:

Изображение 965

  • 1
    Выглядит довольно хорошо для меня. Хотя вы могли бы заменить цикл I циклом foreach для большей ясности.
  • 0
    Спасибо, Крис. Я только что изменил свой код для использования Foreach.
Показать ещё 3 комментария
7

Я обнаружил, что UriBuilder действительно хорошо работает для такого рода вещей:

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

Посмотрите Класс UriBuilder - MSDN для большего количества конструкторов и документации.

6

Простой способ объединить их и убедиться в их правильности:

string.Format("{0}/{1}", Url1.Trim('/'), Url2);
  • 0
    +1, хотя это очень похоже на ответ mdsharpe, который я улучшил в своем ответе. Эта версия прекрасно работает, если Url2 не начинается с / или \, или Url1 случайно не заканчивается на \, или один из них не пуст! :)
4

Здесь метод 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);
    }

Источник: GitHub

  • 0
    Похоже, что это может быть для путей, а не URL-адресов.
  • 0
    @BrianMacKay Согласился, что это выглядит так, но это из класса UrlUtility и используется в контексте объединения URL-адресов.
Показать ещё 2 комментария
3

Я считаю следующее полезным и имеет следующие особенности:

  • Броски на ноль или пробел
  • Принимает params нескольких параметров для нескольких сегментов URL
  • бросает на ноль или пусто

Учебный класс

public static class UrlPath
{
   private static string InternalCombine(string source, string dest)
   {
      if (string.IsNullOrWhiteSpace(source))
         throw new ArgumentException("Cannot be null or white space", nameof(source));

      if (string.IsNullOrWhiteSpace(dest))
         throw new ArgumentException("Cannot be null or white space", nameof(dest));

      return $"{source.TrimEnd('/', '\\')}/{dest.TrimStart('/', '\\')}";
   }

   public static string Combine(string source, params string[] args) 
       => args.Aggregate(source, InternalCombine);
}

тесты

UrlPath.Combine("test1", "test2");
UrlPath.Combine("test1//", "test2");
UrlPath.Combine("test1", "/test2");

// Result = test1/test2

UrlPath.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ;

// Result = test1/test2/test3

UrlPath.Combine("/test1/", "/test2/", null);
UrlPath.Combine("", "/test2/");
UrlPath.Combine("/test1/", null);

// Throws an ArgumentException
  • 0
    @PeterMortensen спасибо за редактирование
3

Я создал эту функцию, которая сделает вашу жизнь проще:

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

Он работает как для URL, так и для обычных путей.

Использование:

    // 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
3

Мое общее решение:

public static string Combine(params string[] uriParts)
{
    string uri = string.Empty;
    if (uriParts != null && uriParts.Any())
    {
        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;
}
  • 0
    Этот вспомогательный метод очень гибок и хорошо работает во многих различных случаях использования. Спасибо!
1

Почему бы просто не использовать следующее.

System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")
  • 0
    Я искал версию PowerShell для этого, которая была бы: [System.IO.Path]::Combine("http://MyUrl.com/","/Images/Image.jpg") однако это не дает результата из: /Images/Image.jpg . Удалите / из второго подпути, и он работает: [System.IO.Path]::Combine("http://MyUrl.com/","Images/Image.jpg")
  • 0
    Хорошая идея, но она терпит неудачу, когда один из параметров является нулевым.
1

Правила при объединении URL с URI

Чтобы избежать странного поведения, есть одно правило:

  • Путь (каталог) должен заканчиваться на '/'. Если путь заканчивается без '/', последняя часть обрабатывается как имя файла и будет объединена при попытке объединить со следующей частью URL.
  • Есть одно исключение: базовый URL-адрес (без информации о каталоге) не должен заканчиваться на '/'
  • часть пути не должна начинаться с '/'. Если он начинается с '/', string.Empty существующая относительная информация из URL удаляется... добавление string.Empty Путь к string.Empty части также удалит относительный каталог из URL!

Если вы следуете правилам выше, вы можете комбинировать URL с кодом ниже. В зависимости от вашей ситуации, вы можете добавить несколько частей "каталога" в 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();
        });
1

Использование:

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

Преимущество в том, что он ведет себя точно так же, как Path.Combine.

1

Вот мой подход, и я буду использовать его и для себя:

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
    Я согласен с вашими пунктами. Код должен выполнять простое объединение двух частей url.
1

Использовать этот:

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);
    }
}
  • 0
    Приятное прикосновение с «WebPath». :) Код может быть излишне плотным, хотя мне трудно на это взглянуть и сказать: да, это прекрасно. Это заставляет меня хотеть видеть юнит-тесты. Может быть, это только я!
  • 1
    x.StartsWith ("/") &&! x.StartsWith ("http") - почему проверка http? что ты получаешь?
Показать ещё 2 комментария
0

Я обнаружил, что конструктор Uri переворачивает '\' на '/'. Таким образом, вы также можете использовать Path.Combine с конструктором Uri.

 Uri baseUri = new Uri("http://MyUrl.com");
 string path = Path.Combine("Images", "Image.jpg");
 Uri myUri = new Uri(baseUri, path);
0

Мы используем следующий простой вспомогательный метод для объединения произвольного количества частей URL:

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

Обратите внимание, что он не поддерживает '../../something/page.htm'-style относительные URL!

0

Простой один вкладыш:

public static string Combine(this string uri1, string uri2) => $"{uri1.TrimEnd('/')}/{uri2.TrimStart('/')}";

Вдохновленный ответом @Matt Sharpe.

0

Обе эти работы:

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

Или же

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

Т.е. если

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

а также

relativePath = "To_Folder"

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

Некоторые ошибки появятся для кода ниже:

 // If you use the below code, some issues will be there in the final URI
 Uri final = new Uri(baseUrl, relativePath);
0

Я использовал этот код для решения проблемы:

string[] brokenBaseUrl = Context.Url.TrimEnd('/').Split('/');
string[] brokenRootFolderPath = RootFolderPath.Split('/');

for (int x = 0; x < brokenRootFolderPath.Length; x++)
{
    //if url doesn't already contain member, append it to the end of the string with / in front
    if (!brokenBaseUrl.Contains(brokenRootFolderPath[x]))
    {
        if (x == 0)
        {
            RootLocationUrl = Context.Url.TrimEnd('/');
        }
        else
        {
            RootLocationUrl += String.Format("/{0}", brokenRootFolderPath[x]);
        }
    }
}
0

Ну, я просто объединяю две строки и использую регулярные выражения для очистки.

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

Итак, вы можете использовать это так:

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

Я объединил все предыдущие ответы:

    public static string UrlPathCombine(string path1, string path2)
    {
        path1 = path1.TrimEnd('/') + "/";
        path2 = path2.TrimStart('/');

        return Path.Combine(path1, path2)
            .Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
    }

    [TestMethod]
    public void TestUrl()
    {
        const string P1 = "http://msdn.microsoft.com/slash/library//";
        Assert.AreEqual("http://msdn.microsoft.com/slash/library/site.aspx", UrlPathCombine(P1, "//site.aspx"));

        var path = UrlPathCombine("Http://MyUrl.com/", "Images/Image.jpg");

        Assert.AreEqual(
            "Http://MyUrl.com/Images/Image.jpg",
            path);
    }
  • 1
    Вы могли бы использовать класс VirtualPathUtiliy для безопасного добавления и удаления конечных слешей. Проверьте мой ответ: stackoverflow.com/a/23399048/3481183
0

Я должен указать, что Path.Combine кажется, работает для этого также напрямую, по крайней мере, в .NET 4.

  • 10
    Если вы используете Path.Combine, вы получите что-то вроде этого: www.site.com/foo\wrong\icon.png
  • 0
    Именно так. Я потратил некоторое время на реализацию функции Uri.Combine именно по этой причине: stackoverflow.com/a/23399048/3481183
-1

Nalarium.Url в пакете Nalarium NuGet делает именно это.

Подпись:

public static String Join(params String[] parameterArray)

Следовательно, вы можете сделать это (предположим, что переменные из базы данных или что-то):

Nalarium.Url.Join("https://domain", id, resource, version, parameters);

Clean.

Это params, поэтому вы можете добавлять параметры по мере необходимости.

-1

Я еще не использовал следующий код, но нашел его во время моих интернет-путешествий, чтобы решить проблему с объединением URL-адресов - надеясь, что это будет кратким (и успешным!) ответом:

VirtualPathUtility.Combine
  • 2
    Не слишком полезно на самом деле. Есть несколько обращений Google, объясняющих некоторые из его проблем, но, помимо того, что в начале не нравится «http: // ...», он фактически удаляет последний подпуть первого аргумента, если он не заканчивается "/"! Хотя описание MSDN звучит нормально!
  • 0
    Я объяснил и предоставил решение этой проблемы в своем ответе stackoverflow.com/a/23399048/3481183

Ещё вопросы

Сообщество Overcoder
Наверх
Меню