Combine relative baseUri with relative path
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)
an开发者_如何学Pythond 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.
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
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".
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"
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);
}
Try:
UriBuilder uriBuilder = new UriBuilder(Settings.Default.ImagesRealtivePath);
uriBuilder.Path += image;
_imagePath = uriBuilder.Uri;
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/images\image.jpg
精彩评论