Uri.ToString Must Die

Update (Oct 2021): The code examples below are no longer true for .NET Framework 4.5, .NET Core 1.0, .NET 5.0 and later. However, Uri.ToString will still unescape certain other characters (such as %20 to ` ` (space), %21 to !, %22 to ", etc.) so I still recommend avoiding it.

If your code uses Uri.ToString, it’s probably a bug.

The Uri.ToString method is documented as returning the “unescaped canonical representation” of the URI. Put simply, this means it’s corrupted. Characters like + and & will become unescaped, which completely changes the meaning of the URI.

Say you want to use WolframAlpha to do some maths:

Uri uri = new Uri("https://www.wolframalpha.com/input/?i=1%2b1");

// WRONG! Returns https://www.wolframalpha.com/input/?i=1+1
uri.ToString();

// Correct! Returns https://www.wolframalpha.com/input/?i=1%2b1
uri.AbsoluteUri;

Or say you want to learn a new language:

Uri uri = new Uri("https://www.google.com/search?q=K%26R");

// WRONG! Returns https://www.google.com/search?q=K&R
uri.ToString();

// Correct! Returns https://www.google.com/search?q=K%26R
uri.AbsoluteUri;

My preference is to use Uri.AbsoluteUri, but that will fail if the URI is relative. In that case, you can use Uri.OriginalString, which simply returns the original string passed to the Uri constructor. Unfortunately, this causes you to lose the small amount of escaping of invalid URIs and canonicalization that the Uri class does perform, so you should ensure your original string is already correctly URL-encoded.

Posted by Bradley Grainger on August 20, 2010