如果只处理 url 编码,我应该使用EscapeUriString吗?
我没有发现现有的答案令人满意,所以我决定更深入地解决这个问题。令人惊讶的是,答案非常简单:
*(几乎*)没有正当理由使用Uri.EscapeUriString. 如果您需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString. *
Uri.EscapeUriString
Uri.EscapeDataString
* 有关有效用例,请参阅最后一段。
为什么是这样?根据文档:
使用 EscapeUriString 方法准备一个未转义的 URI 字符串作为 Uri 构造函数的参数。
这真的没有意义。根据RFC 2396:
URI 始终采用“转义”形式,因为转义或取消转义已完成的 URI 可能会改变其语义。
虽然引用的 RFC 已被RFC 3986淘汰,但这一点仍然存在。让我们通过一些具体的例子来验证它:
csharp http://example.org/
Uri.EscapeUriString不会改变它。
ruby http://example.org/?key=two words
Uri.EscapeUriString将(正确地)为您逃离空间:
http://example.org/?key=two%20words
ruby http://example.org/?parameter=father&son
但是,此字符串不会被 更改Uri.EscapeUriString,因为它假定 & 符号表示另一个键值对的开始。这可能是也可能不是您想要的。
key
father&son
perl http://example.org/?parameter=father%26son
但是,Uri.EscapeUriString也会转义百分比字符,导致双重编码:
http://example.org/?parameter=father%2526son
如您所见,将Uri.EscapeUriString其用于预期目的使得无法将其&用作查询字符串中键或值的一部分,而不是用作多个键值对之间的分隔符。
&
这是因为,为了使它适合转义完整的 URI,它忽略了保留字符,只转义了既不是保留也不是非保留的字符,顺便说一句,这与文档相反。这样你就不会得到类似的东西http%3A%2F%2Fexample.org%2F,但你最终会遇到上面说明的问题。
http%3A%2F%2Fexample.org%2F
最后,如果你的 URI 是有效的,它不需要被转义作为参数传递给 Uri 构造函数,如果它无效,那么调用Uri.EscapeUriString也不是一个神奇的解决方案。实际上,即使不是大多数情况,它也适用于许多情况,但它绝不是可靠的。
您应该始终通过收集键值对和百分比编码来构造您的 URL 和查询字符串,然后将它们与必要的分隔符连接起来。您可以Uri.EscapeDataString用于此目的,但不能使用Uri.EscapeUriString,因为它不会转义保留字符,如上所述。
只有当您无法做到这一点时,例如在处理用户提供的 URI 时,才有意义将其Uri.EscapeUriString用作最后的手段。但是前面提到的警告也适用——如果用户提供的 URI 不明确,结果可能并不理想。