开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜