tags:

views:

1053

answers:

4

I have two Uri objects passed into some code, one is a directory and the other is a filename (or a relative path)

var a = new Uri("file:///C:/Some/Dirs");
var b = new Uri("some.file");

when I try and combine them like this:

var c = new Uri(a,b);

I get

file:///C:/Some/some.file

where I wold expect to get the same effect as with Path.Combine (as that is the old code I need to replace):

file:///C:/Some/Dirs/some.file

I can't think of a clean solution to this.

The ugly solution being to add a / to the Uri if it's not there

string s = a.OriginalString;
if(s[s.Length-1] != '/')
   a = new Uri(s + "/");
A: 

add a slash end of your first uri, URI will ignore more than one slash (/)

var a = new Uri("file:///C:/Some/Dirs/");

EDIT:

var a = new Uri("file:///C:/Some/Dirs");
var b = new Uri("some.file",  UriKind.Relative);
var c = new Uri(Path.Combine(a.ToString(), b.ToString()));
MessageBox.Show(c.AbsoluteUri);
Tolgahan Albayrak
That's the almost exactly code I'm tasked with replacing :)
BCS
i still dont understand what you want :) you have a directory uri and a file uri, and you try to combine them, why you dont want to add a trailing slash directly end of the directory uri.. there is no difference between "file:///c:/some/dir/some.file" and "file:///c:/some/dir//////////////////some.file"
Tolgahan Albayrak
+2  A: 

Well, you're going to have to tell the Uri somehow that the last part is a directory rather than a file. Using a trailing slash seems to be the most obvious way to me.

Bear in mind that for many Uris, the answer you've got is exactly right. For example, if your web browser is rendering

http://foo.com/bar/index.html

and it sees a relatively link of "other.html" it then goes to

http://foo.com/bar/other.html

not

http://foo.com/bar/index.html/other.html

Using a trailing slash on "directory" Uris is a pretty familiar way of suggesting that relative Uris should just append instead of replacing.

Jon Skeet
I'm trying to convert from using strings and Path.* to using Uri and needing to duplicate Path.Combine and that doesn't work this way. It's going to be a PITA if I don't find a nice way to do this.
BCS
Why not create a static method to do it for you, akin to Path.Combine, which is documented to *assume* that the first Uri is meant to be a directory, and will append a slash to it if necessary?
Jon Skeet
(It could even be an extension method, if you wanted and if you're using C# 3.)
Jon Skeet
@Jon: That's what I'v got and am trying to remove. :)
BCS
As luck would have it, All the a's w/o trailing '/' right come from the same function so I can tweak it to generate better input. Actually, as it turns out, I can drop that function in several of those cases because the "new Uri(Uri,Uri)" does that function's job for me.
BCS
A: 

Why not just inherit from Uri and use that, ie. do in constructor what you need to do to fix it up? Refactoring is cheap assuming this is internal to assembly or within reach..

rama-jka toti
That has no advantage that I see over Jon's option. Am I missing something?
BCS
Probably not.. then again, if you have a scheme part in one of them you can already tell implicitly it is the one requiring special attention. This is assuming you have literals all over the place. You either fix them at-site in the literal or with new type.. Perhaps I'm missing something.
rama-jka toti
If I got it corret, best way would be to parse the code for local declarations and assignment expressions and Uri type with scheme part contained. Quite a strong rule, and if it contains it introduce a slash. You will need a good parser but a quick hack could do it too.
rama-jka toti
The Uri's don't come from literals. Some other code is feeding me them after pulling them from runtime sources.
BCS
In that case, Jon's answer with extension method is as good as it gets.. I'd be inclined to say its a runtime-problem aimed at the constructor or insist on fixing the call site :-) You must have heard that Google got blasted because of a similar simple slash incident.
rama-jka toti
A: 

You can try this extension method! Works always! ;-)

 public static class StringExtension
    {
        public static string UriCombine(this string str, string param)
        {
            if (!str.EndsWith("/"))
            {
                str = str + "/";
            }
            var uri = new Uri(str);
            return new Uri(uri, param).AbsoluteUri;
        }
    }

Angelo, Alessandro

Angelo N.