2011-02-07 17 views
13

Estoy buscando una manera limpia de combinar una base relativa Uri con otra ruta relativa. He intentado lo siguiente, pero Uri(Uri, string) y UriBuilder(Uri) requieren Uris absoluto (arrojando InvalidOperationException: Esta operación no es compatible con un URI relativo).Combinar relativeUri relativa con ruta relativa

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

no quiero hacer ninguna manipulación de cadenas feo para asegurarse de que la ruta de la base termina con una barra diagonal, etc.

Respuesta

17

Esto sigue siendo un poco más desordenado de lo que quisiera, pero funciona.

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

He aquí un ejemplo de uso:

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

El combinedImageUrl es ~/ruta/a/images/profile.jpg

-1

Probar:

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

Esto es lo mismo que mi intento 2 ejemplo. Lanza "InvalidOperationException: esta operación no es compatible con un URI relativo" – jrummell

-3

sólo puede utilizar Path.Combine(string, string) lograr esto. Si es una URL relativa, la salida será un poco cobarde, pero sería bastante fácil de corregir, o simplemente podría ignorar el problema y la mayoría de los usos seguirán funcionando.

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

Salida: ~/ruta/a/images \ image.jpg

+3

¿Hay alguna razón por la que se haya bajado la votación? Bajar votos sin hacer ningún comentario es increíblemente inútil. –

+2

No fue el infractor, pero pone una barra invertida en lugar de una barra diagonal, no es correcta para las URL. En particular, esos enlaces en realidad no funcionarán en Firefox en la Mac. – user12861

+0

Path.Combine es para rutas de archivos locales, no URIs – StuartQ

4

Probar:

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

Esto devolverá la cadena "~/ruta/a/imágenes/imagen.jpg".

1

Antes que nada, ¡gracias por la respuesta en esta publicación!

Hice una versión simplificada del método, omitiendo la "complejidad" del uso de la clase Uri. El método solo toma cadenas como parámetros y también devuelve una cadena.

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

Por encima de código podría ser útil para otras personas que quiere exponer un método que proporciona esta funcionalidad sin depender de cualquiera de Uri o VirtualPathUtility, pero sólo cadenas simples.

Por supuesto, puede fácilmente ser modificado para volver Uri - manteniendo la ventaja de analizar los parámetros de cadena:

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

El uso de los dos ejemplos de código anteriores:

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

una versión ligeramente más generalizada de la respuesta de jrummell que acepta que el primer parámetro sea un absoluto o un relativo Uri es:

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