2010-12-08 14 views
11

Necesito combinar dos Uris relativos, p. Ej. ../mypath/ y myimage.png para crear ../mypath/myimage.png. No son rutas de acceso a los archivos en el disco, por lo que Path.Combine no es apropiado (son rutas relativas a recursos para una página web). new Uri arroja un ArgumentOutOfRangeException porque el uri base es relativo (no absoluto).Combinación de dos Uris relativos

¿Tengo alguna otra opción que no sea buscar una barra al final y combinar las rutas yo mismo?

EDIT:

Aquí es un caso de prueba que demuestra que Path.Combine no funcionará para el caso en que el primer URL no contiene ya una barra final:

// The first case fails with result "../testpath\resource.png" 
[TestCase("../testpath", "resource.png", "../testpath/resource.png")] 
[TestCase("../testpath/", "resource.png", "../testpath/resource.png")] 
public void TestPathCombine(string path, string resourceName, string expectedResult) { 
    string result = Path.Combine(path, resourceName); 
    Assert.AreEqual(expectedResult, result); 
} 
+0

posible duplicado de [Combine relative baseUri con ruta relativa] (http: // stackoverflow.com/questions/4925468/combine-relative-baseuri-with-relative-path) –

Respuesta

4

no utilizar ruta .combine como lo es para el camino físico, por lo que podría confundirte con barras. Puedes hacer que tu propia función de Uri se combine. Comprobación de barra en el extremo y añádala a la siguiente.

¿Puede el constructor URI con ayuda de dos argumentos?

new Uri(Uri baseUri, string relativeUri) 
+7

Como dije en la publicación usando ese nuevo constructor de URI, falla con una 'ArgumentOutOfRangeException' porque la baseUri es relativa. Crear mi propia función realmente parece ser mi única opción. –

+1

Creo que es la mejor manera de hacerlo. Toma la ayuda de la clase VirtualPathUtility. Tiene una función combinada, pero no estoy seguro de si se ajusta exactamente a sus necesidades. Pero tiene funciones que pueden ayudar a hacer uno. p.ej. AppendTrailingSlash y AppendTrailingSlash –

+1

VirtualPathUtility.AppendTrailingSlash más la concatenación simple de cadenas resuelve esta pregunta. Sin embargo, al final, decidí requerir y documentar que la barra inclinada final era requerida para la ruta base en primer lugar. –

3

Puede utilizar el constructor Uri que tiene una base y una parte relativa a hacer la combinación - pero tenga en cuenta que el comportamiento será posiblemente no sea el esperado. La clase Uri verá la parte final de su base como un "directorio" o un "archivo" (para ponerlo en términos de ruta). Si ve el final como un archivo, se eliminará. Por ejemplo, si combina http://server/something/ con resource.png obtendrá http://server/something/resource.png.

Ahora omita la barra diagonal: combine http://server/something con resource.png y obtenga http://server/resource.png.

Esto tiene sentido si lo piensas como comenzar con una base Uri de http://server/something.png y preguntar por la relativa uri resource.png: http://server/something.png/resource.png no es lo que estás buscando.

Si SIEMPRE sabe que deben adjuntarse, debe asegurarse de que la base termine con una barra antes de combinar.

8

Si su segunda parte es (como en mi caso) es realmente un nombre de archivo sin ningún escape (y como tal puede contener inválidos caracteres para una url), aquí está la solución que he terminado con:

VirtualPathUtility.Combine(
    VirtualPathUtility.AppendTrailingSlash(relativeUri), 
    Uri.EscapeDataString(fileName)); 

Tenga en cuenta que esta solución no admitirá un uri completo (con esquema, host, puerto): emitirá una excepción con un uri completo. Gracias a Manish Pansiniya por mentioning System.Web.VirtualPathUtility.

Además, como mi nombre del archivo era de hecho una ruta de archivo parcial (algunos nombres de carpeta seguido de nombre de archivo), en lugar de llamar directamente System.Uri.EscapeDataString, tengo llamar a la siguiente función:

/// <summary> 
/// Convert a partial file path to a partial url path. 
/// </summary> 
/// <param name="partialFilePath">The partial file path.</param> 
/// <returns>A partial url path.</returns> 
public static string ConvertPartialFilePathToPartialUrlPath(
    string partialFilePath) 
{ 
    if (partialFilePath == null) 
     return null; 
    return string.Join("/", 
     partialFilePath.Split('/', '\\') 
      .Select(part => Uri.EscapeDataString(part))); 
} 

(Requiere el uso de System.Linq para .Select y fx4 para la cadena utilizada. Sobrecarga de conexión)

Cuestiones relacionadas