Create new URI from Base URI and Relative Path - slash makes a difference?

18,028

Solution 1

Why does a slash make difference when using new URI(baseUri, relativePath)?

Well, that's what happens on the web normally.

For example, suppose I'm looking at http://foo.com/some/file1.html and there's a link to file2.html - that link goes to http://foo.com/some/file2.html, right? Not http://foo.com/some/file1.html/file2.html.

More specifically though, this follows section 5.2.3 of RFC 3986.

5.2.3. Merge Paths

The pseudocode above refers to a "merge" routine for merging a relative-path reference with the path of the base URI. This is accomplished as follows:

  • If the base URI has a defined authority component and an empty path, then return a string consisting of "/" concatenated with the reference's path; otherwise,

  • return a string consisting of the reference's path component appended to all but the last segment of the base URI's path (i.e., excluding any characters after the right-most "/" in the base URI path, or excluding the entire base URI path if it does not contain any "/" characters).

Solution 2

I've been playing around with the Uri constructor with the overload new Uri(baseUri, relativePath). Perhaps others may find the results useful. Here's the output from the test application I wrote:

A) Base Address is domain only
==============================

NO trailing slash on base address, NO leading slash on relative path:
http://foo.com   +  relative1/relative2 :
    http://foo.com/relative1/relative2

NO trailing slash on base address, relative path HAS leading slash:
http://foo.com   +  /relative1/relative2 :
    http://foo.com/relative1/relative2

Base address HAS trailing slash, NO leading slash on relative path:
http://foo.com/   +  relative1/relative2 :
    http://foo.com/relative1/relative2

Base address HAS trailing slash, relative path HAS leading slash:
http://foo.com/   +  /relative1/relative2 :
    http://foo.com/relative1/relative2

B) Base Address includes path
=============================

NO trailing slash on base address, NO leading slash on relative path:
http://foo.com/base1/base2   +  relative1/relative2 :
    http://foo.com/base1/relative1/relative2 
    (removed base2 segment)

NO trailing slash on base address, relative path HAS leading slash:
http://foo.com/base1/base2   +  /relative1/relative2 :
    http://foo.com/relative1/relative2
    (removed base1 and base2 segments)

Base address HAS trailing slash, NO leading slash on relative path:
http://foo.com/base1/base2/   +  relative1/relative2 :
    http://foo.com/base1/base2/relative1/relative2
    (has all segments)

Base address HAS trailing slash, relative path HAS leading slash:
http://foo.com/base1/base2/   +  /relative1/relative2 :
    http://foo.com/relative1/relative2
    (removed base1 and base2 segments)

Solution 3

I was looking for the same, and arrived at the following solution:

var badBase = new Uri("http://amee/noTrailingSlash");
var goodBase = new Uri("http://amee/trailingSlash/");
var f = "relPath";
string badBaseUrl = Path.Combine(badBase,f);
string goodBaseUrl = Path.Combine(goodBase,f);
new Uri(badBaseUrl);  //----> (http://amee/trailingSlash/relPath)
new Uri(goodBaseUrl); //---> (http://amee/trailingSlash/relPath)
Share:
18,028

Related videos on Youtube

user2864740
Author by

user2864740

user2864740

Updated on September 15, 2022

Comments

  • user2864740
    user2864740 over 1 year

    Why does a slash make difference when using new URI(baseUri, relativePath)?

    This constructor creates a Uri instance by combining the baseUri and the relativeUri ..

    And, how can can a relative path be appended safely/consistently to a URI?

    var badBase = new Uri("http://amee/noTrailingSlash");
    var goodBase = new Uri("http://amee/trailingSlash/");
    var f = "relPath";
    new Uri(badBase, f)     // BAD  -> http://amee/relPath
    new Uri(goodBase, f)    // GOOD -> http://amee/trailingSlash/relPath
    

    The desired output is "good" case, even when the initial URI does not have a trailing slash.

  • user2864740
    user2864740 about 10 years
    I was just found your other answer too. Thanks for including the RFC link, as that explicitly answers my "why" question.
  • Jon Skeet
    Jon Skeet about 10 years
    @user2864740: Thanks for adding the appropriate quote :)
  • user2864740
    user2864740 about 10 years
    I don't suppose there is an alternate URI(eitherOrSlash) -> URI(withSlash) without going the URI->String->URI route?
  • Jon Skeet
    Jon Skeet about 10 years
    @user2864740: Not that I'm aware of, I'm afraid :(
  • Steztric
    Steztric over 3 years
    I would never have guessed the behaviour of new Uri() with a base address that has a path. This answer saved me a lot of hair.