代码之家  ›  专栏  ›  技术社区  ›  Andrew Arnott

如何使Uri.EscapeDataString符合RFC 3986

  •  29
  • Andrew Arnott  · 技术社区  · 17 年前

    System.Uri class documentation :

    文档还指出,激活此IRI模式以及RFC 3986行为意味着将uri节元素添加到machine.config,并将其添加到app/web.config文件:

    <configuration>
      <uri>
      <idn enabled="All" />
      <iriParsing enabled="true" />
      </uri>
    </configuration>
    

    但是,无论.config文件中是否存在这种情况,我都会得到与.NET3.5SP1应用程序相同的(非3986)转义行为。 我还需要做些什么才能得到它 Uri.EscapeDataString 要使用RFC 3986规则? (特别是,转义该RFC中定义的保留字符)

    5 回复  |  直到 17 年前
        1
  •  38
  •   Andrew Arnott    17 年前

    由于无法使Uri.EscapeDataString采用RFC3986行为,我编写了自己的符合RFC3986的转义方法。它利用Uri.EscapeDataString,然后将转义“升级”到RFC 3986法规遵从性。

    /// <summary>
    /// The set of characters that are unreserved in RFC 2396 but are NOT unreserved in RFC 3986.
    /// </summary>
    private static readonly string[] UriRfc3986CharsToEscape = new[] { "!", "*", "'", "(", ")" };
    
    /// <summary>
    /// Escapes a string according to the URI data string rules given in RFC 3986.
    /// </summary>
    /// <param name="value">The value to escape.</param>
    /// <returns>The escaped value.</returns>
    /// <remarks>
    /// The <see cref="Uri.EscapeDataString"/> method is <i>supposed</i> to take on
    /// RFC 3986 behavior if certain elements are present in a .config file.  Even if this
    /// actually worked (which in my experiments it <i>doesn't</i>), we can't rely on every
    /// host actually having this configuration element present.
    /// </remarks>
    internal static string EscapeUriDataStringRfc3986(string value) {
        // Start with RFC 2396 escaping by calling the .NET method to do the work.
        // This MAY sometimes exhibit RFC 3986 behavior (according to the documentation).
        // If it does, the escaping we do that follows it will be a no-op since the
        // characters we search for to replace can't possibly exist in the string.
        StringBuilder escaped = new StringBuilder(Uri.EscapeDataString(value));
    
        // Upgrade the escaping to RFC 3986, if necessary.
        for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++) {
            escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0]));
        }
    
        // Return the fully-RFC3986-escaped string.
        return escaped.ToString();
    }
    
        2
  •  4
  •   Community Mohan Dere    9 年前

    在.NET4.5中,这实际上已经被修复,默认情况下可以正常工作,请参见 here

    PUrify (在遇到这个问题后)这将通过本文中方法的一个变化来处理.NET 4.5之前版本(适用于3.5)和Mono的工作 post . PUrify不会更改EscapeDataString,但它允许您拥有带有保留字符的URI,这些字符不会被转义。

        3
  •  2
  •   Community Mohan Dere    9 年前

    我意识到这个问题和答案已经有几年历史了,但我想当我遇到麻烦时,我会分享我的发现 compliance under .Net 4.5 .

    如果您的代码在asp.net下运行,只需将项目设置为目标4.5并在具有4.5或更高版本的计算机上运行,您仍然可能会获得4.0行为。你需要确保 <httpRuntime targetFramework="4.5" /> 在web.config中设置。

    从…起 this blog article on msdn ,

    如果没有 <httpRuntime targetFramework> 属性存在于 在Web.config中,我们假设应用程序需要4.0怪癖行为。

        4
  •  0
  •   Marc Gravell    17 年前

    您使用的是什么版本的框架?看起来这些变化中有很多是在( from MSDN

        5
  •  0
  •   Agent_L    14 年前

    我找不到更好的答案(无论是100%的框架还是100%的重新实现),所以我创造了这个讨厌的东西。似乎正在与OAuth合作。

    class al_RFC3986
    {
        public static string Encode(string s)
        {
            StringBuilder sb = new StringBuilder(s.Length*2);//VERY rough estimate
            byte[] arr = Encoding.UTF8.GetBytes(s);
    
            for (int i = 0; i < arr.Length; i++)
            {
                byte c = arr[i];
    
                if(c >= 0x41 && c <=0x5A)//alpha
                    sb.Append((char)c);
                else if(c >= 0x61 && c <=0x7A)//ALPHA
                    sb.Append((char)c);
                else if(c >= 0x30 && c <=0x39)//123456789
                    sb.Append((char)c);
                else if (c == '-' || c == '.' || c == '_' || c == '~')
                    sb.Append((char)c);
                else
                {
                    sb.Append('%');
                    sb.Append(Convert.ToString(c, 16).ToUpper());
                }
            }
            return sb.ToString();
        }
    }
    
    推荐文章