2011-02-07 10 views
13

Je cherche une manière propre de combiner un URI de base relatif avec un autre chemin relatif. J'ai essayé le suivant, mais Uri(Uri, string) et UriBuilder(Uri) exigent Uris absolu (jetant InvalidOperationException: cette opération n'est pas prise en charge pour un URI relatif).Combiner baseUri relatif avec le chemin relatif

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

Je ne veux pas faire toute manipulation de chaîne laid pour vous assurer que le chemin de base se termine par une barre oblique, etc.

Répondre

17

Ceci est encore un peu messier que je le voudrais, mais cela fonctionne.

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

Voici un exemple d'utilisation:

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

Le combinedImageUrl est ~/chemin/vers/images/profile.jpg

-1

Essayez:

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

Ceci est le même que mon exemple de tentative 2. Il lève "InvalidOperationException: cette opération n'est pas prise en charge pour un URI relatif" – jrummell

-3

Vous pouvez simplement utiliser Path.Combine(string, string) pour y parvenir. S'il s'agit d'une URL relative, la sortie sera un peu géniale, mais il serait assez facile à corriger - ou vous pourriez simplement ignorer le problème et la plupart des utilisations devraient encore fonctionner.

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

Sortie: ~/chemin/vers/images \ image.jpg

+3

Y at-il une raison pour laquelle cela a été downvoted? Downvoting sans commentaire est incroyablement inutile. –

+2

N'était pas le downvoter, mais il met dans une barre oblique inverse au lieu d'une barre oblique, pas correct pour les URL. En particulier, ces liens ne fonctionneront pas sur Firefox sur Mac. – user12861

+0

Path.Combine est pour les chemins de fichiers locaux, pas les URI – StuartQ

4

Essayez:

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

Cela renverra la chaîne "~/chemin/vers/images/image.jpg".

1

Tout d'abord, merci pour la réponse sur ce post!

J'ai fait une version simplifiée de la méthode, en sautant la "complexité" de l'utilisation de la classe Uri. La méthode prend seulement des chaînes comme paramètres et renvoie également une chaîne.

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

code ci-dessus peut être utile pour les autres qui veulent exposer une méthode offrant cette fonctionnalité sans dépendre soit Uri ou VirtualPathUtility, mais seulement des chaînes simples.

peut bien sûr être facilement modifié pour revenir Uri - en conservant le bénéfice des paramètres de chaîne d'analyse syntaxique:

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

Utilisation des deux exemples de code ci-dessus:

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

Une version légèrement plus généralisée de la réponse de jrummell qui accepte le premier paramètre comme étant un absolu ou un parent Uri est:

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