Background: I’m trying to some some URL manipulation for an MVC application. I’ve written an HtmlHelper extension method that replaces on query string value with another. The method takes the current request string, manually splits the query part (so as to prevent Foo=1&Foo=Hello%2c%20World!&Foo=2 from being read as Foo=1,Hello, World,2), and then tries to use UriBuilder and Uri to get a URL.
Problem: For some reason, Uri.ToString partially decodes query strings. As a quick test, I fired up LINQPad and ran the following:
var ub = new System.UriBuilder("http://foobar");
ub.Query = "NY%26A"; // NY&A
ub.Uri.Dump();
ub.Uri.ToString().Dump();
ub.Uri.Query.Dump();
ub.ToString().Dump();
The results are:
http://foobar/?NY&A
http://foobar/?NY&A
?NY%26A
http://foobar:80/?NY%26A
I say partially decoding, because if I use lots of escaped characters, it decodes some and leaves others in place:
var ub = new System.UriBuilder("http://foobar");
ub.Query = "!%40%23%24%25%5E%26*()"; // !@#$%^&*()
ub.Uri.Dump();
ub.Uri.ToString().Dump();
ub.Uri.Query.Dump();
ub.ToString().Dump();
And the results:
http://foobar/?!@%23$%25^&*()
http://foobar/?!@%23$%25^&*()
?!%40%23%24%25%5E%26*()
http://foobar:80/?!%40%23%24%25%5E%26*()
Question: Can someone explain what is going on?