I thought I would share a few things I've learned with Uri and UriBuilder.
Uri has a boat load of properties, but once you start looking/playing with them, you realized, it's really just an easy way to pull the URL apart. It's not really a nice way to put things back together for later use. UriBuilder helps but still seems like a weak teasing cousin to Uri. Here's what I mean, take a look at the code snippet below and the output.
static void Main( string[] args )
{
Uri habsUrl = new Uri( "http://canadiens.nhl.com:12345/team/SomePage.aspx?service=page&page=NewsPage&articleid=451283" );
Console.WriteLine( "habsUrl.ToString() = " + habsUrl.ToString() );
Console.WriteLine();
Console.WriteLine( "Properties in alphabetical order" );
Console.WriteLine( new string( '-', 40 ) );
Console.WriteLine( "habsUrl.AbsolutePath = " + habsUrl.AbsolutePath );
Console.WriteLine( "habsUrl.AbsoluteUri = " + habsUrl.AbsoluteUri );
Console.WriteLine( "habsUrl.Authority = " + habsUrl.Authority );
Console.WriteLine( "habsUrl.DnsSafeHost = " + habsUrl.DnsSafeHost );
Console.WriteLine( "habsUrl.Fragment = " + habsUrl.Fragment );
Console.WriteLine( "habsUrl.Host = " + habsUrl.Host );
Console.WriteLine( "habsUrl.HostNameType = " + habsUrl.HostNameType );
Console.WriteLine( "habsUrl.IsAbsoluteUri = " + habsUrl.IsAbsoluteUri );
Console.WriteLine( "habsUrl.IsDefaultPort = " + habsUrl.IsDefaultPort );
Console.WriteLine( "habsUrl.IsUnc = " + habsUrl.IsUnc );
Console.WriteLine( "habsUrl.IsWellFormedOriginalString() = " + habsUrl.IsWellFormedOriginalString() );
Console.WriteLine( "habsUrl.LocalPath = " + habsUrl.LocalPath );
Console.WriteLine( "habsUrl.PathAndQuery = " + habsUrl.PathAndQuery );
Console.WriteLine( "habsUrl.Port = " + habsUrl.Port );
Console.WriteLine( "habsUrl.Query = " + habsUrl.Query );
Console.WriteLine( "habsUrl.Scheme = " + habsUrl.Scheme );
for( int i = 0; i < habsUrl.Segments.Length; i++ )
{
Console.WriteLine( "habsUrl.Segments[" + i + "] = " + habsUrl.Segments[i] );
}
Console.WriteLine( "habsUrl.UserEscaped = " + habsUrl.UserEscaped );
Console.WriteLine( "habsUrl.UserInfo = " + habsUrl.UserInfo );
Console.WriteLine( "Methods in alphabetical order" );
Console.WriteLine( new string( '-', 40 ) );
Console.WriteLine( "habsUrl.GetComponents( UriComponents.HostAndPort, UriFormat.SafeUnescaped ) = " + habsUrl.GetComponents( UriComponents.HostAndPort, UriFormat.SafeUnescaped ) );
Console.WriteLine( "habsUrl.GetComponents( UriComponents.HostAndPort, UriFormat.Unescaped ) = " + habsUrl.GetComponents( UriComponents.HostAndPort, UriFormat.Unescaped ) );
Console.WriteLine( "habsUrl.GetComponents( UriComponents.HostAndPort, UriFormat.UriEscaped ) = " + habsUrl.GetComponents( UriComponents.HostAndPort, UriFormat.UriEscaped ) );
Console.WriteLine( "habsUrl.GetComponents( UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped ) = " + habsUrl.GetComponents( UriComponents.HttpRequestUrl, UriFormat.SafeUnescaped ) );
Console.WriteLine( "habsUrl.GetComponents( UriComponents.SchemeAndServer, UriFormat.SafeUnescaped ) = " + habsUrl.GetComponents( UriComponents.SchemeAndServer, UriFormat.SafeUnescaped ) );
Console.WriteLine( "habsUrl.GetComponents( UriComponents.SerializationInfoString, UriFormat.SafeUnescaped ) = " + habsUrl.GetComponents( UriComponents.SerializationInfoString, UriFormat.SafeUnescaped ) );
Console.WriteLine( "" );
Console.WriteLine( "habsUrl.GetLeftPart(UriPartial.Authority) = " + habsUrl.GetLeftPart( UriPartial.Authority ) );
Console.WriteLine( "habsUrl.GetLeftPart(UriPartial.Path) = " + habsUrl.GetLeftPart( UriPartial.Path ) );
Console.WriteLine( "habsUrl.GetLeftPart(UriPartial.Query) = " + habsUrl.GetLeftPart( UriPartial.Query ) );
Console.WriteLine( "habsUrl.GetLeftPart(UriPartial.Scheme) = " + habsUrl.GetLeftPart( UriPartial.Scheme ) );
Console.ReadLine();
}

Notice how easy it is with Uri to cherry pick off the individual part (the "http" schrme or the 12345 port) but I ask you, how would you pull out JUST what you needed to repoint the current page to a new page in the same directory? Well there are two ways. One easy way is to just use the "~/NewPage.aspx" and let .NET handle the tilde, and two, whip out your own using the above properties. BUT! There is yet another way I learned Fri doing this blog! Notice, the GetComponents method? There's also the GetLeftPart method too! I've seen these before but never paid them much attention until tonight and MAN, they give you so muc for free!
What's the big deal you ask? hhhhmm You mustn't have moved your webapp from one box to another using a virtual server then? Or tried to move a page from one directory to another? Or worse, use the SAME box BUT changed the port you're using? Or maybe you've had an IT Admin call you up complaining how your app won't work with SSL? These situations are most likely caused cause you hard coded something, OR you forgot something (like the port number in the latter case).
With using the Uri and UriBuilder class you can easily handle the above situations and not get yourself into trouble.
Now it's time to grab a coffee and get coding!
Bonus
That "~" tilde character is sometimes overlooked and it's unfortunate. That one little character (called the Root Operator) is a handy magical wonder of the ASP.NET world! It handles sooo many magical things for you. So much that in .NET 2.0, MS introduced a new class called VirtualPathUtility to help you out. There are some cool methods on there, like
- ToAbsolutePath which translates the tilde to the proper virtual directory you're currently using
- Combine which is JUST like Path.Combine but for the web (and you SHOULD know what the Path.Combine is right? Right? RIGHT?)
- MakeRelative is sort of the opposite of the ToAbsolutePath one, gives you a relative path (using the ../ notation)
HttpRequest object has a QueryString property as well which helps you manipulate (ala add and remove parameters) which is AWESOME (and was the source of my major malfunction which originally generated this blog entry). To play with this, you should be familiar with the NameValueCollection. It's too bad they postfixed the same with "String" cause it might lead someone to think that's the object type it returns. But now that you know about it, you know better. HAHA
Source Code: https://techtidbits.svn.codeplex.com/svn/2009/UrlUtility
Resources: you've been haacked, The Most Useful .NET Utility Classes Developers Tend To Reinvent Rather Than Reuse