Skip to content

Instantly share code, notes, and snippets.

@glennblock
Last active January 1, 2016 08:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glennblock/8120163 to your computer and use it in GitHub Desktop.
Save glennblock/8120163 to your computer and use it in GitHub Desktop.
using System;
using System.Net;
using System.Reflection;
namespace UriTest
{
//a mono version of the ForceCanonicalPathAndQuery code here: http://stackoverflow.com/questions/781205/getting-a-url-with-an-url-encoded-slash
class Program
{
static void Main(string[] args)
{
var uri = new Uri("http://www.yahoo.com/%2F?Foo=Bar%2F#frag");
UriHelper.ForceCanonicalPathAndQuery(uri);
Console.WriteLine ("uri.ToString() - " + uri.ToString ());
Console.WriteLine ("uri.AbsoluteUri - " + uri.AbsoluteUri);
Console.WriteLine ("uri.Host - " + uri.Host);
Console.WriteLine ("uri.Query - " + uri.Query);
Console.WriteLine ("uri.PathAndQuery - " + uri.PathAndQuery);
Console.WriteLine ("uri.AbsolutePath - " + uri.AbsolutePath);
Console.WriteLine ("uri.Fragment - " + uri.Fragment);
}
public class UriHelper {
private static Type uriType = typeof(Uri);
private static FieldInfo sourceField;
private static FieldInfo queryField;
private static FieldInfo pathField;
private static FieldInfo cachedToStringField;
private static FieldInfo cachedAbsoluteUriField;
static UriHelper ()
{
sourceField = uriType.GetField ("source", BindingFlags.NonPublic | BindingFlags.Instance);
queryField = uriType.GetField ("query", BindingFlags.NonPublic | BindingFlags.Instance);
pathField = uriType.GetField ("path", BindingFlags.NonPublic | BindingFlags.Instance);
cachedToStringField = uriType.GetField ("cachedToString", BindingFlags.NonPublic | BindingFlags.Instance);
cachedAbsoluteUriField = uriType.GetField ("cachedAbsoluteUri", BindingFlags.NonPublic | BindingFlags.Instance);
}
public static void ForceCanonicalPathAndQuery(Uri uri)
{
var source = (string) sourceField.GetValue (uri);
cachedToStringField.SetValue (uri, source);
cachedAbsoluteUriField.SetValue (uri, source);
var fragPos = source.IndexOf ("#");
var queryPos = source.IndexOf ("?");
var start = source.IndexOf (uri.Host) + uri.Host.Length;
var pathEnd = queryPos == -1 ? fragPos : queryPos;
if (pathEnd == -1)
pathEnd = source.Length+1;
var path = queryPos > -1 ? source.Substring (start, pathEnd - start) : source.Substring (start);
pathField.SetValue (uri, path);
queryField.SetValue(uri, fragPos > -1 ? source.Substring(queryPos, fragPos - queryPos) : source.Substring(queryPos));
}
}
}
}
/*
outputs:
uri.ToString() - http://www.yahoo.com/%2F?Foo=Bar%2F#frag
uri.AbsoluteUri - http://www.yahoo.com/%2F?Foo=Bar%2F#frag
uri.Host - www.yahoo.com
uri.Query - ?Foo=Bar%2F
uri.PathAndQuery - /%2F?Foo=Bar%2F
uri.AbsolutePath - /%2F
uri.Fragment - #frag
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment