EscapeUriString 和 EscapeDataString 有什么区别?
EscapeUriString 和 EscapeDataString 有什么区别?
如果只涉及到URL编码,我应该使用EscapeUriString吗?
我发现现有的答案都不令人满意,所以我决定深入挖掘来解决这个问题。令人惊讶的是,答案非常简单:
几乎没有使用Uri.EscapeUriString
的有效理由。如果您需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString
。*
*请参见最后一段以了解有效的用例。
为什么呢?根据文档:
使用EscapeUriString方法将未转义的URI字符串准备好,以成为Uri构造函数的参数。
这并没有什么意义。根据RFC 2396:
URI始终处于“转义”形式,因为对已完成的URI进行转义或取消转义可能会更改其语义。
虽然引用的RFC已被RFC 3986所废除,但这一点仍然成立。让我们通过查看一些具体的示例来验证它:
-
您有一个简单的URI,例如:
http://example.org/
Uri.EscapeUriString
不会改变它。
-
您决定手动编辑查询字符串而不考虑转义:
http://example.org/?key=two words
Uri.EscapeUriString
将(正确地)为您转义空格:
http://example.org/?key=two%20words
-
您决定再次手动编辑查询字符串:
http://example.org/?parameter=father&son
但是,此字符串不会被Uri.EscapeUriString
更改,因为它认为“&”表示另一个键值对的开始。这可能是您想要的,也可能不是您想要的。
-
您决定实际上希望
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 不明确,则结果可能不理想。