I’m looking for a clean way to combine a relative base Uri with another relative path. I’ve tried the following, but Uri(Uri, string) and UriBuilder(Uri) require absolute Uris (throwing InvalidOperationException: This operation is not supported for a relative URI).
// 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;
I don’t want to do any ugly string manipulation to make sure the base path ends with a trailing slash, etc.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This is still a bit messier than I’d like, but it works.
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);
}
}
Here’s an example usage:
Uri imageUrl = new Uri("profile.jpg", UriKind.Relative);
Uri baseImageUrl = new Uri("~/path/to/images", UriKind.Relative);
Uri combinedImageUrl = baseImageUrl.Combine(image);
The combinedImageUrl is
~/path/to/images/profile.jpg
Method 2
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));
This will return the string “~/path/to/images/image.jpg”.
Method 3
First of all, thanks for the response on this post!
I made a simplified version of the method, skipping the “complexity” of using the Uri class. The method only takes strings as parameters and is also return a string.
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;
}
Above code might be useful for others who wants to expose a method providing this functionality without being dependent on either Uri or VirtualPathUtility, but only simple strings.
Can of course easily be modified to return Uri – still keeping the benefit of parsing string parameters:
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);
}
Usage of both of above code examples:
Image.ImageUrl = MakeRelativeUrl("path", "to", "images", "image.jpg").ToString();
// Image.ImageUrl == "~/path/to/images/image.jpg"
Method 4
A slightly more generalized version of jrummell’s answer that accepts the first parameter to be either an absolute or a relative Uri is:
/// <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);
}
Method 5
Try:
UriBuilder uriBuilder = new UriBuilder(Settings.Default.ImagesRealtivePath); uriBuilder.Path += image; _imagePath = uriBuilder.Uri;
Method 6
You can just use Path.Combine(string, string) to achieve this. If it’s a relative URL the output will be a little funky, but it would be easy enough to correct- or you could simply ignore the issue and most usages should still work.
Path.Combine("~/path/to/images", "image.jpg");
Output: ~/path/to/imagesimage.jpg
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0