I've seen a number of posts that ask about using non-conforming Uris, but none of them have a good answer. I'm writing a Windows Phone control and it needs to request ATOM data using HTTP GET. The URL needs to include the characters %3d (the equal sign) in it. This is non-negotiable as it's a third-party service over which I have no control. Imagine a URL like the following:
http://host.com?arg1=val1&arg=val2%3d
I'm using WebClient with DownloadStringAsync, but it only accepts Uri objects, not URL in strings. The Uri object automatically unescapes those characters and sends:
http://host.com?arg1=val1&arg=val2=
This fails. There's a deprecated constructor argument "UserExcaped" that is exactly what I need, but it's not available. I fear that my only option is to implement my own string download method using a raw socket and minimal HTTP support.
Any other thoughts? Help is very much appreciated!!
UPDATE
string apps = "http://blah.com/api?prev=AAAAAAA%3d&next=BBBBBBB";
var u = new Uri(apps);
string apps2 = u.ToString();
Debug.Assert(apps == apps2); // That %3d will always be converted to an equals sign
I should also point out, that if I try to be clever by encoding the percent as %25 (so it's "prev=AAAAAA%253d&next=BBBBB") then I get that exact literal string with %25 still intact! It's just %3d that it's aggressive about converting to an equals sign.
The Uri class is designed to be like that. MSDN:
As part of canonicalization in the constructor for some schemes, escaped representations are compacted. The schemes for which URI will compact escaped sequences include the following: file, http, https, net.pipe, and net.tcp. For all other schemes, escaped sequences are not compacted.
Have you tried using HttpWebRequest instead? It's a bit more work than a WebClient, but it lets you pass a string as the destination.
Edit - Another approach could be to create your own UriParser which allows the encoded version. An example of extending the UriParser can be found here.
For others not running Windows Phone, you can use reflection to fix this.
MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (getSyntax != null && flagsField != null)
{
foreach (string scheme in new[] { "http", "https" })
{
UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { scheme });
if (parser != null)
{
int flagsValue = (int)flagsField.GetValue(parser);
//0x20000 is the SimpleUserSyntax attribute
if ((flagsValue & 0x20000) != 0)
flagsField.SetValue(parser, flagsValue & ~0x20000);
}
}
}
Uri u = new Uri("http://host.com?arg1=val&arg=val2%3d");
//At this point, the %3d remains as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With