Search code examples
c#.netvb.net.net-4.7.2uribuilder

UriBuilder unexpected behavior, or is it?


The documentation says

The port number defines the protocol port for contacting the host referenced in the URI. If a port is not specified as part of the URI, the Port property returns the value of -1 to indicate that the default port value for the protocol scheme will be used to connect to the host. If the Port property is set to a value of -1, this indicates that the default port value for the protocol scheme will be used to connect to the host.

(I don't care c# or VB, current code happened to be VB)

Public Sub Main()
        
    dim logonLink as string = "https://website/application/login.aspx"
    Console.WriteLine("RETURN: {0}", logonLink)

    Dim uriBuilder As New UriBuilder(logonLink)     
    Console.WriteLine("HOST: {0}", uriBuilder.Host)
    Console.WriteLine("PORT: {0}", uriBuilder.Port)

End Sub

However, when this code runs, if the link contains http - port number shows 80, and https - 443. While I expect -1. This is in FW4.7.2

Do I miss something?

PS: Uri does same thing but at least is has IsDefaultPort

Dim uri As Uri = nothing
Uri.TryCreate(logonLink, UriKind.Absolute, uri)
Console.WriteLine("URI PORT: {0}", uri.Port)
Console.WriteLine("URI PORT def: {0}", uri.IsDefaultPort)

Solution

  • You are doing more than just reading the .Port property. First you are calling the constructor;

    This constructor initializes a new instance of the UriBuilder class with the Fragment, Host, Path, Port, Query, Scheme, and Uri properties set as specified in uri.

    Which references Uri.Port;

    The port number defines the protocol port used for contacting the server referenced in the URI. If a port is not specified as part of the URI, the Port property returns the default value for the protocol. If there is no default port number, this property returns -1.

    So if you use this constructor, the port number will be the default port of any well known protocol. If you use any other constructor, the port number should be left as the default -1.

    Reading the current source code for UriBuilder, I found this surprise;

            public Uri Uri
            {
                get
                {
                    if (_changed)
                    {
                        _uri = new Uri(ToString());
                        SetFieldsFromUri();
                        _changed = false;
                    }
                    else
                    {
                        Debug.Assert(_uri is not null);
                    }
                    return _uri;
                }
            }
    

    Merely reading the .Uri can change the value of all other properties. So if you leave the .Port number alone, but change anything else. Then read the .Uri property. The .Port number will also change to the default port.