开发者

Combining two relative Uris

I need to combine two relative Uris, e.g. ../mypath/ and myimage.png to create ../mypath/myimage.png. They are not paths to files on disk so Path.Combine is not appropriate (they are relative paths to resources for a web page). new Uri throws an ArgumentOutOfRangeException because the base uri is relative (not absolute).

Do I have any options other than checking for a trailing slash and then combining the paths myself?

EDIT:

Here is a test case that demonstrates that Path.Combine will not work for the case when the first url does not alr开发者_如何学编程eady contain a trailing slash:

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


If your second part is (like in my own case) really a file name without any escaping (and as such may contain invalids chars for an url), here is the solution I have ended up with:

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

Beware that this solution will not support a full uri (with scheme, host, port): it will throw an exception with a full uri. Thanks to Manish Pansiniya for mentioning System.Web.VirtualPathUtility.

In addition, as my file name was in fact a partial file path (some folder names followed by file name), rather than calling directly System.Uri.EscapeDataString, I have call the following function:

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

(Requires using System.Linq for .Select and fx4 for the used string.Join overload.)


You can use the Uri constructor that takes a base and a relative part to do the combination - but note that the behavior will possibly not be what you expect. The Uri class will see the end part of your base as either a "directory" or a "file" (to put it in path terms). If it sees the end as a file, that will get removed.

For example, combining http://server/something/ with resource.png will give you http://server/something/resource.png.

Now omit the trailing slash: combine http://server/something with resource.png and get http://server/resource.png.

This makes sense if you think of it as starting with a base Uri of http://server/something.png and asking for the relative uri resource.png: http://server/something.png/resource.png isn't what you're looking for.

If you ALWAYS know that they should be appended, you need to make sure that the base ends with a slash before combining.


Do not use path.combine as it is for physcial path so it might confuse you with slashes. You can make your own function of Uri combine. Checking slash at the end and append it to next one.

Can URI constructor with two argument help?

new Uri(Uri baseUri, string relativeUri)
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜