2011-02-07 3 views
13

Я ищу чистый способ объединить относительную базу Uri с другим относительным путем. Я пробовал следующее, но Uri(Uri, string) и UriBuilder(Uri) требуют абсолютного Uris (throwing InvalidOperationException: эта операция не поддерживается для относительного URI).Объединить относительный baseUri с относительным путем

// where Settings.Default.ImagesPath is "~/path/to/images" 
// attempt 1 
_imagePath = new Uri(Settings.Default.ImagesPath, image); 

// attempt 2 
UriBuilder uriBuilder = new UriBuilder(Settings.Default.ImagesPath); 
uriBuilder.Path += image; 
_imagePath = uriBuilder.Uri; 

Я не хочу делать какие-либо уродливые манипуляции со строками, чтобы убедиться, что базовый путь заканчивается слешем и т.д.

ответ

17

Это еще немного грязнее, чем хотелось бы, но это работает.

public static class UriExtensions 
{ 
    public static Uri Combine(this Uri relativeBaseUri, Uri relativeUri) 
    { 
     if (relativeBaseUri == null) 
     { 
      throw new ArgumentNullException("relativeBaseUri"); 
     } 

     if (relativeUri == null) 
     { 
      throw new ArgumentNullException("relativeUri"); 
     } 

     string baseUrl = VirtualPathUtility.AppendTrailingSlash(relativeBaseUri.ToString()); 
     string combinedUrl = VirtualPathUtility.Combine(baseUrl, relativeUri.ToString()); 

     return new Uri(combinedUrl, UriKind.Relative); 
    } 
} 

Вот пример использования:

Uri imageUrl = new Uri("profile.jpg", UriKind.Relative); 
Uri baseImageUrl = new Uri("~/path/to/images", UriKind.Relative); 
Uri combinedImageUrl = baseImageUrl.Combine(image); 

combinedImageUrl является ~/путь/к/изображения/profile.jpg

-1

Try:

UriBuilder uriBuilder = new UriBuilder(Settings.Default.ImagesRealtivePath); 
uriBuilder.Path += image; 
_imagePath = uriBuilder.Uri; 
+0

Это то же, что и в примере с моей попыткой. Он выбрасывает «InvalidOperationException: эта операция не поддерживается для относительного URI» – jrummell

-3

Вы можете просто использовать Path.Combine(string, string) для достижения этой цели. Если это относительный URL-адрес, вывод будет немного напуганным, но его было бы достаточно легко исправить или вы могли бы просто проигнорировать проблему, и большинство обычаев должно работать.

Path.Combine("~/path/to/images", "image.jpg"); 

Выход: ~/путь/к/изображений \ Image.jpg

+3

Есть ли причина, по которой это было приостановлено? Нисходящее без комментариев невероятно бесполезно. –

+2

Не был downvoter, но он помещает обратную косую черту вместо прямой косой черты, не подходит для URL-адресов. В частности, эти ссылки фактически не будут работать в Firefox на Mac. – user12861

+0

Path.Combine предназначен для локальных путей к файлам, а не URI – StuartQ

4

Try:

UriBuilder builder = new UriBuilder(); 
Uri baseUri = builder.Uri; 
builder.Path = Settings.Default.ImagesRealtivePath; 
if (!builder.Path.EndsWith("/")) 
    builder.Path += "/"; 
_imagePath = baseUri.MakeRelativeUri(new Uri(builder.Uri, image)); 

Это вернет строка "~/путь/to/images/image.jpg".

1

Прежде всего, спасибо, что ответ на это сообщение!

Я сделал упрощенную версию метода, пропустив «сложность» использования класса Uri. Метод принимает только строки в качестве параметров, а также возвращает строку.

public static string MakeRelativeUrl(params string[] relativePaths) 
{ 
    var res = "~/"; 
    foreach (var relativePath in relativePaths) 
    { 
     string baseUrl = VirtualPathUtility.AppendTrailingSlash(res); 
     res = VirtualPathUtility.Combine(baseUrl, relativePath); 
    } 
    return res; 
} 

Приведенный выше код может быть полезным для тех, кто хочет выставить метод, обеспечивающий эту функциональность, не будучи зависимыми от любой Ури или VirtualPathUtility, но только простые строки.

Может конечно быть легко изменен, чтобы вернуть Ури - все еще сохраняя преимущество разборе параметров строки:

public static Uri MakeRelativeUrl(params string[] relativePaths) 
{ 
    var res = "~/"; 
    foreach (var relativePath in relativePaths) 
    { 
     string baseUrl = VirtualPathUtility.AppendTrailingSlash(res); 
     res = VirtualPathUtility.Combine(baseUrl, relativePath); 
    } 
    return new Uri(res, UriKind.Relative); 
} 

Использование обоих приведенных выше примеров кода:

Image.ImageUrl = MakeRelativeUrl("path", "to", "images", "image.jpg").ToString(); 
// Image.ImageUrl == "~/path/to/images/image.jpg" 
1

Несколько более обобщенное версия ответа jrummell, который принимает первый параметр как абсолютный или относительный Uri:

/// <summary> 
    /// Combines two <see cref="Uri"/>s. 
    /// </summary> 
    /// <param name="baseUri">Relative or absolute base uri.</param> 
    /// <param name="relativeUri">Uri to be appended.</param> 
    public static Uri Combine(this Uri baseUri, Uri relativeUri) 
    { 
     if (baseUri == null) throw new ArgumentNullException("baseUri"); 
     if (relativeUri == null) throw new ArgumentNullException("relativeUri"); 

     string baseUrl = VirtualPathUtility.AppendTrailingSlash(baseUri.ToString()); 
     string combinedUrl = VirtualPathUtility.Combine(baseUrl, relativeUri.ToString()); 

     return new Uri(combinedUrl, baseUri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative); 
    }