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 already 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With