EscapeUriString和EscapeDataString有什么区别?

时间:2010-12-09 09:23:52

标签: .net urlencode

如果只处理网址编码,我应该使用EscapeUriString

6 个答案:

答案 0 :(得分:177)

我没有找到满意的答案,所以我决定深入挖掘一下这个问题。令人惊讶的是,答案非常简单:

没有正当理由使用Uri.EscapeUriString。如果您需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString

这是为什么?根据{{​​3}}:

  

使用EscapeUriString方法准备一个未转义的URI字符串作为Uri构造函数的参数。

这并没有多大意义。根据{{​​3}}:

  

URI总是在"转义"表单,因为转义或取消转换已完成的URI可能会改变其语义。

虽然引用的RFC已被documentation废弃,但这一点仍然存在。让我们通过查看一些具体的例子来验证它:

  1. 你有一个简单的URI,如下所示:

    http://example.org/
    

    Uri.EscapeUriString无法改变它。

  2. 您决定手动编辑查询字符串而不考虑转义:

    http://example.org/?key=two words
    

    Uri.EscapeUriString会(正确地)为你逃避空间:

    http://example.org/?key=two%20words
    
  3. 您决定进一步手动编辑查询字符串:

    http://example.org/?parameter=father&son
    

    但是,Uri.EscapeUriString不会更改此字符串,因为它假定“&”符号表示另一个键值对的开头。这可能是你想要的也可能不是。

  4. 您确定您确实希望key参数为father&son,因此您可以通过转义&符来手动修复以前的网址:

    http://example.org/?parameter=father%26son
    

    但是,Uri.EscapeUriString也将转义百分比字符,从而导致双重编码:

    http://example.org/?parameter=father%2526son
    
  5. 如您所见,将Uri.EscapeUriString用于其预期目的使得无法将&用作查询字符串中的键或值的一部分,而不是作为多个键值对之间的分隔符

    这是因为,在错误的尝试使其适合转义完整的URI时,它忽略了保留字符,只转义既不保留也不保留的字符,BTW与RFC 2396相反。这样您就不会得到像http%3A%2F%2Fexample.org%2F这样的内容,但最终会遇到上述问题。

    最后,如果您的URI有效,则不需要将其转义为作为参数传递给Uri construtor,如果它无效,则调用Uri.EscapeUriString isn&#39 ; ta魔术解决方案。实际上,它会在许多情况下发挥作用,如果不是大多数情况,但它绝不可靠。

    您应该始终通过收集键值对和百分比编码构建URL和查询字符串,然后将它们与必要的分隔符连接起来。您可以将Uri.EscapeDataString用于此目的,但不能Uri.EscapeUriString,因为它不会转义保留字符,如上所述。

答案 1 :(得分:95)

始终使用EscapeDataString(有关原因的详细信息,请参阅下面的Livven's answer

编辑:删除了两者在编码方面的差异的死链接

答案 2 :(得分:54)

加号(+)字符可以揭示这些方法之间的差异。在简单的URI中,加号字符表示" space"。考虑向谷歌查询“快乐的猫”":

  

https://www.google.com/?q=happy+cat

这是一个有效的URI(试一试),EscapeUriString不会修改它。

现在考虑向Google查询"快乐的c ++":

  

https://www.google.com/?q=happy+c++

这是一个有效的URI(试一试),但它产生了对#34; happy c"的搜索,因为这两个优点被解释为空格。为了解决这个问题,我们可以通过" happy c ++"到EscapeDataString和voila *

  

https://www.google.com/?q=happy+c%2B%2B

*)编码数据字符串实际上是#happy;%20c%2B%2B&#34 ;; %20是空格字符的十六进制,%2B是加号字符的十六进制。

如果您正在使用UriBuilder,那么您只需要EscapeDataString来正确转义整个URI的某些组件。 @ Livven对这个问题的回答进一步证明没有理由使用EscapeUriString

答案 3 :(得分:5)

source中的评论清楚地说明了这一区别。为什么这些信息不是通过XML文档注释提出的,这对我来说是一个谜。

<强> EscapeUriString:

  

此方法将转义任何非保留字符或   毫无保留的性格,包括百分号。注意   EscapeUriString也不会转义'#'符号。

<强> EscapeDataString:

  

此方法将转义任何非预留的字符   性格,包括百分号。

所以区别在于它们如何处理保留的字符。 EscapeDataString逃脱了他们; EscapeUriString没有。

根据RFC,保留字符为::/?#[]@!$&'()*+,;=

为完整起见,未保留的字符为字母数字和-._~

两种方法都转义既不保留也不保留的字符。

我不同意EscapeUriString %是邪恶的将军notion。我认为只有非法字符(如空格)而不是保留字符的方法才有用。但它在如何处理%字符方面确实有一个怪癖。百分比编码的字符(EscapeUriString后跟2个十六进制数字)在URI中是 legal 。我认为%如果它检测到这种模式会更有用,并且当它立即以2个十六进制数字进行时避免编码element { --main-bg-color: brown; }

答案 4 :(得分:2)

一个简单的例子

var data = "example.com/abc?DEF=あいう\x20えお";

Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));

/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/

答案 5 :(得分:0)

我使用加密字符串作为 URL 参数(例如 http://example.com/Test/myencryptedkey/param2/param3),因此没有任何 C# 加密方法可以提供安全的 url 参数。我最终使用了以下模式:

加密期间: Uri.EscapeDataString(myencryptedkey).Replace('%', '~');

解密期间: Uri.UnescapeDataString(myencryptedkey.Replace('~', '%'));

请注意,在加密期间,替换发生在 EscapeDataString() 之后,而在解密期间,替换发生在 UnescapeDataString() 之前;