14

System.Uri constructor insists on unescaping %2f sequences as foward slashes, when it sees them in path portion of URL. How could I avoid that behaiviour?

I've seen Connect ticket on this thig, but workaround is not working for .net 4 as far is I understand.

Artem Tikhomirov
  • 21,077
  • 10
  • 46
  • 66
  • 1
    http://stackoverflow.com/a/18511985/420849 - this is solution for similar problem in PowerShell – Boo Aug 29 '13 at 13:16

3 Answers3

6

It keeps the original string internally, for example, the following code:

    Uri u = new Uri("http://www.example.com/path?var=value%2fvalue");
    Console.WriteLine(u.OriginalString);

will display

http://www.example.com/path?var=value%2fvalue

EDIT: I have update the code found in the Connect Link Workaround for recent .NET versions. Here it is:

// System.UriSyntaxFlags is internal, so let's duplicate the flag privately
private const int UnEscapeDotsAndSlashes = 0x2000000;
private const int SimpleUserSyntax = 0x20000;

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;
    uriSyntaxFlags = (int)uriSyntaxFlags & ~SimpleUserSyntax;
    fieldInfo.SetValue(uriParser, uriSyntaxFlags);
}

Of course, it's a hack, so you should use it at your own risks :-)

Simon Mourier
  • 123,662
  • 18
  • 237
  • 283
  • Yes, but `new Uri("http://www.example.com/value%2fvalue").ToString()` produces `"http://www.example.com/value/value"`. I should edit question though - thanks for the tip. – Artem Tikhomirov Apr 25 '11 at 18:05
  • Totally offtopic, but thanks for your work on HAP. Have been using it for ages. – Artem Tikhomirov Apr 25 '11 at 18:08
  • 1
    @Artem - thanks :-). for the Uri, I think it's 100% by design, per RFC 3986. But note value%2fvalue in the PATH part or in the QUERY part is not handled the same. You can also use uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.SafeUnescaped) to have "almost" the original string (except for the PATH part). – Simon Mourier Apr 26 '11 at 06:08
  • Sad part is that HttpWebRequest uses System.Uri and one of our systems with plain JSON over HTTP interface requires %2f sequence in PATH part of the query URL. Well, I think it means sockets. – Artem Tikhomirov Apr 27 '11 at 18:19
  • @Artem - I have updated my answer with an adaptation of the "connect" workaround – Simon Mourier Apr 27 '11 at 19:46
4

As I have posted in this question, you can disable this behaviour via a configuration:

<configuration>
  <uri>
    <schemeSettings>
      <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes"/>
    </schemeSettings>
  </uri>
</configuration>
Community
  • 1
  • 1
Pencho Ilchev
  • 3,152
  • 17
  • 21
0

Try to URI.EscapeUriString before construct new URI. It makes %2F looking like %252F and it's work just fine in my case.

Aliaksei Kliuchnikau
  • 13,339
  • 4
  • 56
  • 70