如果只处理url编码,我应该使用EscapeUriString?
Liv*_*ven 204
我没有发现现有的答案令人满意,所以我决定深入挖掘一下这个问题.令人惊讶的是,答案非常简单:
没有正当理由可以使用Uri.EscapeUriString.如果需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString.
为什么是这样?根据文件:
使用EscapeUriString方法将非转义URI字符串准备为Uri构造函数的参数.
这没有多大意义.根据RFC 2396:
URI总是处于"转义"形式,因为转义或取消转换已完成的URI可能会改变其语义.
虽然引用的RFC已被RFC 3986淘汰,但重点仍然存在.让我们通过查看一些具体的例子来验证它:
你有一个简单的URI,如下所示:
http://example.org/
Run Code Online (Sandbox Code Playgroud)
Uri.EscapeUriString 不会改变它.
您决定手动编辑查询字符串而不考虑转义:
http://example.org/?key=two words
Run Code Online (Sandbox Code Playgroud)
Uri.EscapeUriString 将(正确)为你逃离空间:
http://example.org/?key=two%20words
Run Code Online (Sandbox Code Playgroud)您决定进一步手动编辑查询字符串:
http://example.org/?parameter=father&son
Run Code Online (Sandbox Code Playgroud)
但是,此字符串不会更改Uri.EscapeUriString,因为它假定&符号表示另一个键值对的开始.这可能是也可能不是你想要的.
您确定您实际上想要key参数father&son,因此您可以通过转义&符来手动修复以前的URL:
http://example.org/?parameter=father%26son
Run Code Online (Sandbox Code Playgroud)
但是,Uri.EscapeUriString也将转义百分比字符,导致双重编码:
http://example.org/?parameter=father%2526son
Run Code Online (Sandbox Code Playgroud)如您所见,使用Uri.EscapeUriString其预期目的使得无法将其&用作查询字符串中的键或值的一部分,而不是作为多个键值对之间的分隔符.
这是因为,在错误的尝试使其适合转义完整的URI时,它会忽略保留字符,并且只转义既不保留也不保留的字符,BTW与文档相反.这样你最终得不到类似的东西http%3A%2F%2Fexample.org%2F,但你最终会遇到上面说明的问题.
最后,如果您的URI有效,则不需要将其转义为作为参数传递给Uri construtor,如果它无效,那么调用Uri.EscapeUriString也不是一个神奇的解决方案.实际上,它可以在许多情况下工作,但不是大多数情况,但它绝不可靠.
您应该始终通过收集键值对和百分比编码构建URL和查询字符串,然后将它们与必要的分隔符连接起来.您可以使用Uri.EscapeDataString此目的,但不能Uri.EscapeUriString,因为它不会转义保留字符,如上所述.
Jcl*_*Jcl 105
EscapeDataString始终使用(有关原因的更多信息,请参阅下面的Livven的答案)
编辑:删除了两个编码方式不同的死链接
Set*_*eth 54
加号(+)可以揭示这些方法之间的差异.在简单的URI中,加号表示"空格".考虑向Google查询"快乐猫":
这是一个有效的URI(试一试),EscapeUriString不会修改它.
现在考虑查询Google的"happy c ++":
这是一个有效的URI(尝试它),但它产生了对"happy c"的搜索,因为这两个加号被解释为空格.要修复它,我们可以将"happy c ++"传递给EscapeDataString瞧*:
*)编码数据字符串实际上是"happy%20c%2B%2B"; %20是空格字符的十六进制,%2B是加号字符的十六进制.
如果您正在使用UriBuilder,那么您只需要EscapeDataString正确地转义整个URI的某些组件.@Livven对这个问题的回答进一步证明了没有理由使用EscapeUriString.
一个简单的例子
\n\nvar data = "example.com/abc?DEF=\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\\x20\xe3\x81\x88\xe3\x81\x8a";\n\nConsole.WriteLine(Uri.EscapeUriString(data));\nConsole.WriteLine(Uri.EscapeDataString(data));\nConsole.WriteLine(System.Net.WebUtility.UrlEncode(data));\nConsole.WriteLine(System.Web.HttpUtility.UrlEncode(data));\n\n/*\n=>\nexample.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A\nexample.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A\nexample.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A\nexample.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a\n*/\nRun Code Online (Sandbox Code Playgroud)\n
来源中的评论清楚地说明了差异.为什么这些信息不是通过XML文档注释提出的,这对我来说是一个谜.
EscapeUriString:
此方法将转义任何非保留或未保留字符的字符,包括百分号.请注意,EscapeUriString也不会转义'#'符号.
EscapeDataString:
此方法将转义任何非保留字符的字符,包括百分号.
所以区别在于它们如何处理保留字符.EscapeDataString逃避他们; EscapeUriString才不是.
根据RFC,保留字符是::/?#[]@!$&'()*+,;=
为完整起见,未保留的字符是字母数字和 -._~
两种方法都转义既不保留也不保留的字符.
我不同意与一般观念认为EscapeUriString是邪恶的.我认为只有非法字符(例如空格)而不是保留字符的方法才有用.但它在如何处理%角色方面确实有一个怪癖.百分比编码字符(%后跟2个十六进制数字)在URI中是合法的.我认为EscapeUriString如果它检测到这种模式并且%在它立即以2个十六进制数字进行时避免编码将会更有用.
| 归档时间: |
|
| 查看次数: |
81655 次 |
| 最近记录: |