.net 为什么UriBuilder.query不转义(url编码)查询字符串?

cfh9epnr  于 2023-05-30  发布在  .NET
关注(0)|答案(3)|浏览(138)

UriBuilder.Query属性“包含URI中包含的任何查询信息。”According to the docs“,则根据RFC 2396对查询信息进行转义。”
基于此,由于此属性是可写的,我假设当您设置它时,System.UriBuilder将解析您的查询字符串,并根据RFC 2396进行转义(url编码)。特别是,{和}不在非保留字符集中,因此它们应该根据RFC 2396的第9页进行转义。但是,System.UriBuilder似乎没有进行任何转义。
我是否需要手动对参数进行Server.URLEncode,或者有没有办法让System.UriBuilder来处理编码?
下面是我的示例代码。你可以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);
    }
}
6pp0gazn

6pp0gazn1#

builder.Uri.AbsoluteUri

就是你要找的机器人,在你的情况下,它会回来
http://www.bing.com/?param=%7B'blah'%7D
考虑到知道&+=符号是否应该编码的困难,在分配给.Query属性时,最好自己进行转义。

mf98qq94

mf98qq942#

在实践中,我发现您需要自己手动转义查询参数。System.Uri.AbsoluteUri将 * 尝试 * 为您转义(如spender's answer中所述),但可能不会成功。例如,给定一个值someemail+test@gmail.com,AbsoluteUri将保留+未转义,当它应该被转义为%2B时。否则,当查询字符串被解码时,+将被转换为空格,留下someemail test@gmail.com作为最终解码值。
底线是,您需要自己转义它,以确保它被正确转义。
在用dotPeek查看了UriBuilder.Query get/set代码后,我不得不得出结论,文档只是写得很差。而不是“查询信息根据RFC 2396被转义”,它应该说“查询信息应该根据RFC 2396被转义”。
从下面的System.UriBuilder.Query的dotPeek反编译中可以看到,在查询getter或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,然而,试图逃避的东西。注意getter中对this.GetParts的调用:

[__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);
  }
}
mv1qrgav

mv1qrgav3#

UriBuilder从API开始就完全崩溃了:它提供的API不允许实现适当的转义,因为它无法区分您想要做什么(这是转义的全部意义!)。通过提供单个复合Query作为string,您无法表达以下不同的用例:

  • companyName = Alice&Bob,需要转义为companyName=companyName=Alice%26Bob
  • companyName = Alice & purgeCache,应为companyName=Alice&purgeCache

这会因为可能的查询而变得复杂,例如

  • companyName = 100%great,应为companyName=100%25great
  • expression = 1234%56,应为expression=1234%2556

需要有一种方法来表示哪些部分是需要转义的单个组件,哪些是与&连接的单独部分。一个string属性无法提供这一点,所以UriBuilder采取猜测的方式...可预测的结果:经常工作,有时壮观的休息与没有办法解决问题(除了逃避自己击败了整个原因的类)。
目前,当您尝试使用上述示例在UriBuilder上设置Query时,它会给出以下结果:

  • ?companyName=Alice&Bob(错误)
  • ?companyName=Alice&purgeCache(正确,这是UriBuilder猜测的解释)
  • ?companyName=100%25great(正确,因为%gr不可能是有效的转义,它猜对了)
  • ?expression=1234V(错误,%56可能看起来像是一个可能的转义,但它不是故意的)

相关问题