Why does the URI constructor remove part of path from the baseUri argument?
Asked Answered
C

2

6
public class Program
{
    public static void Main()
    {
        Uri baseUri = new Uri("http://localhost:7777/BasePath/");
        Uri uri = new Uri(baseUri, "/controller");
        Console.WriteLine(uri);
    }
}

Is it the intend behavior to wipe /BasePath out from uri and the final result be http://localhost:7777/controller?

Caernarvonshire answered 13/11, 2018 at 17:8 Comment(3)
Because the / in /controller indicates "from root" where root is http://localhost:7777.Kaiserslautern
You need to do new Uri(baseUri, "./controller") to state that your path is relative from the current path (denoted by the dot). This will return http://localhost:7777/BasePath/controller.Gow
Or keep your baseUri and your relativeUri separate. Uri baseUri = new Uri("http://localhost:7777"); Uri uri = new Uri(baseUri, "/BasePath/controller"); That way there's nothing to accidentally overwrite.Jhvh
J
8

I had to dig into the documentation for the constructor you're calling.

public Uri (Uri baseUri, string relativeUri);

Additionally, if the relativeUri begins with a slash, then it will replace any relative part of the baseUri.

It's the intended behavior. If you specify a relative path that begins with a slash, it assumes that the relative path is the entire relative path, so it discards any relative path already included in baseUri.

Jhvh answered 13/11, 2018 at 17:12 Comment(4)
I do not see that. var myUri = "something.com/path1"; var finalUri = new Uri(myUri, "path2"); and finalUri.AbsoluteUri will be "something.com/path2".Handbag
In the documentation, it says that the baseUri must end with a trailing slash if you want the path retained.Irvingirwin
@SENya You could add another or edit this answer to provide more info. In the OP the base URI already ends with a trailing slash, so adding one can't answer the question. The question was why part of the base uri path gets removed when it's combined with a relative URI. In the OP the relative uri begins with a slash.Jhvh
I fixed my problem by adding a trailing slash to my base uri. Previously: https://foo.bar/api/v3 -> https://fo.bar/api/v3/. This ensures that the trailing part of the baseUri is not stripped.Circumfuse
A
1

I wrote a simple unit test for Uri(baseUri, relativeUri) constructor .NET 7.0 and found out that the relative part of the baseUri is preserved only in one case, when:

  • baseUri ends with slash '/'
  • relativeUri to be added does not start with '/'

all cases below are successful

    [Theory]
    [InlineData("http://my.host.net",      "some/path",  "http://my.host.net/some/path")]
    [InlineData("http://my.host.net/net",  "/some/path", "http://my.host.net/some/path")]
    [InlineData("http://my.host.net/net",  "some/path",  "http://my.host.net/some/path")]
    [InlineData("http://my.host.net/net",  "some/path/", "http://my.host.net/some/path/")]
    [InlineData("http://my.host.net/net/", "/some/path", "http://my.host.net/some/path")]
    [InlineData("http://my.host.net/net/", "some/path",  "http://my.host.net/net/some/path")]
    [InlineData("http://my.host.net/net/", "some/path/", "http://my.host.net/net/some/path/")]
    public void CreateUriTest(string baseUrl, string path, string full)
    {
        var baseUri = new Uri(baseUrl);
        var fullUri = new Uri(baseUri, path);
        Assert.Equal(full, fullUri.ToString());
    }

MSDN for .NET 7.0 explanation for Uri(Uri, String) constructor is a bit unclear. It has 2 contradictory statements:

If the baseUri has relative parts (like /api), then the relative part must be terminated with a slash, (like /api/), if the relative part of baseUri is to be preserved in the constructed Uri.

Additionally, if the relativeUri begins with a slash, then it will replace any relative part of the baseUri

The second statement always wins. In other words, starting '/' of the relativeUri does replace the relative part of the baseUri regardless of if it ends with a '/' or not.

Astra answered 4/6, 2024 at 13:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.