13

I need to request the following URL inside my application:

http://feedbooks.com/type/Crime%2FMystery/books/top

When I run the following code:

Uri myUri = new Uri("http://feedbooks.com/type/Crime%2FMystery/books/top");

The Uri constructor decodes the %2F into a literal /, and I get a 404 error because it has changed the URL to:

http://feedbooks.com/type/Crime/Mystery/books/top

The Uri class has a constructor that takes a parameter dontEscape, but that constructor is deprecated and setting it to true has no effect.

My first thought was to do something like:

Uri myUri = new Uri("http://feedbooks.com/type/Crime%252FMystery/books/top");

With the hopes that it would convert %25 into a literal %, but that didn't work either.

Any ideas how to create a correct Uri object for this particular URL in .NET?

asked Feb 23, 2010 at 18:02
2
  • um... did you try \% (or \\%)... :(
    apandit
    Commented Feb 23, 2010 at 18:06
  • I love the question. Now, please give a Java answer for java.io.URI which has the same damn problem, but without the flags (near as I can tell)!
    davidbak
    Commented Nov 24, 2015 at 4:54

4 Answers 4

8

It's a bit easier in .NET 4.0. You can put a setting in your config file like this:

<uri> 
<schemeSettings>
 <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>

It only works for the 'http' and 'https' schemes.

Or here's a new version of the LeaveDotsAndSlashesEscaped method. It doesn't need a particular Uri instance, just call it when your application starts up:

private void LeaveDotsAndSlashesEscaped()
{
 var getSyntaxMethod = 
 typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
 if (getSyntaxMethod == null)
 {
 throw new MissingMethodException("UriParser", "GetSyntax");
 }
 var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
 var setUpdatableFlagsMethod = 
 uriParser.GetType().GetMethod("SetUpdatableFlags", BindingFlags.Instance | BindingFlags.NonPublic);
 if (setUpdatableFlagsMethod == null)
 {
 throw new MissingMethodException("UriParser", "SetUpdatableFlags");
 }
 setUpdatableFlagsMethod.Invoke(uriParser, new object[] {0});
}
ChrisW
56.2k14 gold badges123 silver badges234 bronze badges
answered Aug 26, 2011 at 9:19
0
6

I ran into the same problem using 2.0...

I discovered a workaround posted at this blog:

// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
private const int UnEscapeDotsAndSlashes = 0x2000000;
public static void LeaveDotsAndSlashesEscaped(Uri uri)
{
 if (uri == null)
 {
 throw new ArgumentNullException("uri");
 }
 FieldInfo fieldInfo = uri.GetType().GetField("m_Syntax", BindingFlags.Instance | BindingFlags.NonPublic);
 if (fieldInfo == null)
 {
 throw new MissingFieldException("'m_Syntax' field not found");
 }
 object uriParser = fieldInfo.GetValue(uri);
 fieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
 if (fieldInfo == null)
 {
 throw new MissingFieldException("'m_Flags' field not found");
 }
 object uriSyntaxFlags = fieldInfo.GetValue(uriParser);
 // Clear the flag that we don't want
 uriSyntaxFlags = (int)uriSyntaxFlags & ~UnEscapeDotsAndSlashes;
 fieldInfo.SetValue(uriParser, uriSyntaxFlags);
}

It works perfectly.

Hope this helps (better late than never!)

answered May 17, 2010 at 17:48
1
  • Awesome! Stackoverflow never ceases to amaze me. Commented May 21, 2010 at 13:08
2

This is a bug I filed a while back. It's supposed to be fixed in 4.0, but I'm not holding my breath. Apparently it's still a problem in the RC.

answered Feb 23, 2010 at 18:12
1
  • Sorry, but I haven't found any workaround for this yet. It's a bad one. Go vote it up. Commented Feb 23, 2010 at 18:16
1

By combining the 2 previous answers you can have a method you only need to call once per process that works both on .net 4 and .net 3.5.

// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
private const int UnEscapeDotsAndSlashes = 0x2000000;
private void LeaveDotsAndSlashesEscaped()
{
 var getSyntaxMethod = 
 typeof (UriParser).GetMethod("GetSyntax", BindingFlags.Static | BindingFlags.NonPublic);
 if (getSyntaxMethod == null)
 {
 throw new MissingMethodException("UriParser", "GetSyntax");
 }
 var uriParser = getSyntaxMethod.Invoke(null, new object[] { "http" });
 FieldInfo flagsFieldInfo = typeof(UriParser).GetField("m_Flags", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.SetField | BindingFlags.Instance);
 if (flagsFieldInfo == null)
 {
 throw new MissingFieldException("UriParser", "m_Flags");
 }
 int flags = (int) flagsFieldInfo.GetValue(uriParser);
 // unset UnEscapeDotsAndSlashes flag and leave the others untouched
 flags = flags & ~UnEscapeDotsAndSlashes;
 flagsFieldInfo.SetValue(uriParser, flags);
}
answered Oct 16, 2014 at 15:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.