Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't UriBuilder.query escaping (url encoding) the query string?

Tags:

c#

.net

The UriBuilder.Query property "contains any query information included in the URI." According to the docs, "the query information is escaped according to RFC 2396."

Based on this, and since this property is writable, I assumed that when you set it, System.UriBuilder would parse your query string, and escape (url encode) according to RFC 2396. In particular, the { and } are not in the unreserved character set, and so they should be escaped according to page 9 of RFC 2396. But, it appears that System.UriBuilder is not doing any escaping.

Do I need to manually Server.URLEncode the params, or is there a way to get System.UriBuilder to handle the encoding?

Here's my sample code. You can run this on ideone.com and see that, indeed, nothing is URL encoded.

using System;

public class Test
{
    public static void Main()
    {
        var baseUrl = new System.Uri("http://www.bing.com");
        var builder = new System.UriBuilder(baseUrl);
        string name = "param";
        string val = "{'blah'}";
        builder.Query = name + "=" + val;
        
        // Try several different ouput methods; none will be URL encoded
        Console.WriteLine(builder.ToString());
        Console.WriteLine(builder.Uri.ToString());
        Console.WriteLine(builder.Query);
    }
}
like image 898
Josh Avatar asked Jul 04 '14 14:07

Josh


1 Answers

In practice I have found that you need to manually escape your query params yourself. System.Uri.AbsoluteUri will attempt to escape things for you (as mentioned in spender's answer), but it may not succeed. For instance, given a the value [email protected], AbsoluteUri will leave the + unescaped, when it should be escaped as %2B. Otherwise, when the query string is decoded, the + will be transformed into a space, leaving someemail [email protected] as the final decoded value.

The bottom line is, you need to escape it yourself to ensure it is escaped correctly.

After reviewing the code in UriBuilder.Query get/set code with dotPeek, I have to conclude that the docs are simply written poorly. Instead of "the query information is escaped according to RFC 2396," it should say "the query information should be escaped according to RFC 2396."

As you can see from the dotPeek decompilation of System.UriBuilder.Query below, there is no automatic escaping happening in the query getter or setter.

[__DynamicallyInvokable]
public string Query
{
  [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
  {
    return this.m_query;
  }
  [__DynamicallyInvokable] set
  {
    if (value == null)
      value = string.Empty;
    if (value.Length > 0)
      value = (string) (object) '?' + (object) value;
    this.m_query = value;
    this.m_changed = true;
  }
}

System.Uri.AbsoluteUri, however, makes an attempt to escape things. Note the call to this.GetParts in the getter:

[__DynamicallyInvokable]
public string Authority
{
  [__DynamicallyInvokable] get
  {
    if (this.IsNotAbsoluteUri)
      throw new InvalidOperationException(System.SR.GetString("net_uri_NotAbsolute"));
    else
      return this.GetParts(UriComponents.Host | UriComponents.Port, UriFormat.UriEscaped);
  }
}
like image 110
Josh Avatar answered Oct 31 '22 19:10

Josh