EscapeUriString和EscapeDataString有什么区别?


192

如果仅处理url编码,我应该使用EscapeUriString


10
始终使用@ 来转义每个单独的Uri.EscapeDataString(),如@Livven的答案中所述。使用其他方法,系统根本没有足够的信息来为每个可能的输入产生预期的结果。
Timo

Answers:


112

EscapeDataString始终使用(有关原因的更多信息,请参见下面的Livven回答

编辑:删除死链接到两者如何在编码上有所不同


3
我不确定该链接是否实际上提供了更多信息,因为它涉及转义而不是转义。
史蒂文·

1
基本上是相同的区别。如果您实际阅读过这篇文章,那么中间的桌子上实际上会进行转义(而不是转义)以显示差异(也进行比较URLEncode)。
Jcl 2013年

2
对我来说仍然不清楚-如果我不转义整个URI,而仅转义其中的一部分-(即查询字符串参数的数据)怎么办?我是否为URI转义数据,还是EscapeDataString暗示完全不同的东西?
BrainSlugs83

4
...做了一些测试,好像我想要EscapeDataString作为URI参数。我使用字符串“ I heart C ++”进行了测试,而EscapeUriString并未对“ +”字符进行编码,它只是将它们原样保留,EscapeDataString正确地将它们转换为“%2B”。
BrainSlugs83

7
这是一个不好的答案。您永远不要使用EscapeUriString,这没有任何意义。请参阅以下Livven的答案(并投票赞成)。
布兰登·帕多克

241

我发现现有的答案并不令人满意,因此我决定更深入地解决该问题。令人惊讶的是,答案非常简单:

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

*有关有效的用例,请参见最后一段。

为什么是这样?根据文档

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

这真的没有道理。根据RFC 2396

URI始终采用“转义”形式,因为对完整的URI进行转义或转义可能会更改其语义。

尽管引用的RFC已被RFC 3986取代但这一点仍然存在。让我们通过查看一些具体示例进行验证:

  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,因此可以通过转义与号来手动修复先前的URL:

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

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

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

如您所见,使用 Uri.EscapeUriString其用于预期目的将使其无法&用作查询字符串中的键或值的一部分,而不能用作多个键值对之间的分隔符。

这是因为,为了使其适合转义完整URI,它会忽略保留字符,而仅转义既非保留也非保留的字符,这与文档相反。这样,您最终不会得到类似http%3A%2F%2Fexample.org%2F,但是您确实遇到了上述问题。


最后,如果您的URI有效,则无需进行转义即可将其作为参数传递给Uri构造函数,如果无效,则调用 Uri.EscapeUriString也不是一个神奇的解决方案。实际上,它在很多情况下(即使不是大多数情况下)都可以工作,但绝不是可靠的。

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

仅当您不能执行此操作时(例如,在处理用户提供的URI时),才可以将其Uri.EscapeUriString用作最后的手段。但是前面提到的警告适用–如果用户提供的URI不明确,则结果可能不理想。


4
哇,谢谢您终于弄清楚了这个问题。前两个答案不是很有帮助。
EverPresent

3
非常正确。EscapeUriString(类似于Win32中EscapeUrl的默认行为)是由不了解URI或转义的人创建的。创建带有格式错误的URI并有时将其转换为预期版本的尝试是一种误导。但是它没有可靠地执行此操作所需的信息。它也经常被用来代替EscapeDataString,这也是很成问题的。我希望EscapeUriString不存在。每次使用都是错误的。
布兰登·帕多克

4
很好地解释了+1,它比仅接受链接的答案要好得多
Ehsan Sajjad

1
这个答案需要更多的关注。这是正确的方法。其他答案存在无法产生预期结果的情况。
Timo

1
......当然encodeURI/ Uri.EscapeUriString不需要经常为encodeURIComponent/ Uri.EscapeDataString(因为当你有必须在一个URI上下文中使用盲网址deaing),但是,这并不意味着它没有自己的位置。
Crescent Fresh

56

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

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

这是一个有效的URI(请尝试),并且EscapeUriString不会对其进行修改。

现在考虑向Google查询“ happy c ++”:

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

这是一个有效的URI(请尝试),但是它会搜索“ happy c”,因为两个加号被解释为空格。要解决此问题,我们可以将“ happy c ++”传递给EscapeDataString和瞧*

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

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

如果您UriBuilder按原样使用,则只需要EscapeDataString适当地转义整个URI的某些组件即可。@Livven对这个问题的回答进一步证明,确实没有理由使用EscapeUriString


谢谢。例如,当您有一个需要编码的绝对URI字符串时该怎么办"https://www.google.com/?q=happy c++"。看来我需要手动分割“?”,还是有更好的方法?
wensveen 2015年

如果要将整个URL作为参数传递给另一个URL,请使用EscapeDataString。如果您提供的URL是实际URL,则是,您只想分割为?
塞斯(Seth)2015年

7

来源中的注释清楚地说明了差异。为什么不通过XML文档注释来提供此信息对我来说是一个谜。

EscapeUriString:

此方法将转义不是保留字符或保留字符的任何字符,包括百分号。请注意,EscapeUriString也不会转义“#”符号。

EscapeDataString:

此方法将转义不是保留字符的任何字符,包括百分号。

因此区别在于它们如何处理保留字符。EscapeDataString逃脱他们;EscapeUriString才不是。

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

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

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

我不同意与一般观念认为EscapeUriString是邪恶的。我认为只转义非法字符(例如空格)而不保留字符的方法很有用。但是它在处理%角色方面确实有一个古怪之处。百分号编码的字符(%后跟2个十六进制数字)在URI中是合法的。我认为EscapeUriString,如果它检测到此模式并%在立即以2个十六进制数字开头时避免编码,那将更加有用。


1

一个简单的例子

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
*/
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.