.net EscapeUriString 和 EscapeDataString 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4396598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between EscapeUriString and EscapeDataString?
提问by user496949
If only deal with url encoding, I should use EscapeUriString?
如果只处理 url 编码,我应该使用EscapeUriString吗?
采纳答案by Jcl
Use EscapeDataStringalways (for more info about why, see Livven's answerbelow)
EscapeDataString始终使用(有关原因的更多信息,请参阅下面的Livven 回答)
Edit: removed dead link to how the two differ on encoding
编辑:删除了两者在编码上有何不同的死链接
回答by Livven
I didn't find the existing answers satisfactory so I decided to dig a little deeper to settle this issue. Surprisingly, the answer is very simple:
我没有找到令人满意的现有答案,所以我决定深入挖掘来解决这个问题。令人惊讶的是,答案非常简单:
There is (almost*) no valid reason to ever use Uri.EscapeUriString. If you need to percent-encode a string, always use Uri.EscapeDataString.
有(几乎*)没有正当理由使用Uri.EscapeUriString. 如果您需要对字符串进行百分比编码,请始终使用Uri.EscapeDataString.
* See the last paragraph for a valid use case.
* 有关有效用例,请参阅最后一段。
Why is this? According to the documentation:
为什么是这样?根据文档:
Use the EscapeUriString method to prepare an unescaped URI string to be a parameter to the Uri constructor.
使用 EscapeUriString 方法准备一个未转义的 URI 字符串作为 Uri 构造函数的参数。
This doesn't really make sense. According to RFC 2396:
这真的没有意义。根据RFC 2396:
A URI is always in an "escaped" form, since escaping or unescaping a completed URI might change its semantics.
URI 总是采用“转义”形式,因为转义或取消转义完整的 URI 可能会改变其语义。
While the quoted RFC has been obsoleted by RFC 3986, the point still stands. Let's verify it by looking at some concrete examples:
虽然引用的 RFC 已被RFC 3986废弃,但这一点仍然存在。我们来看一些具体的例子来验证一下:
You have a simple URI, like this:
http://example.org/Uri.EscapeUriStringwon't change it.You decide to manually edit the query string without regard for escaping:
http://example.org/?key=two wordsUri.EscapeUriStringwill (correctly) escape the space for you:http://example.org/?key=two%20wordsYou decide to manually edit the query string even further:
http://example.org/?parameter=father&sonHowever, this string is not changed by
Uri.EscapeUriString, since it assumes the ampersand signifies the start of another key-value pair. This may or may not be what you intended.You decide that you in fact want the
keyparameter to befather&son, so you fix the previous URL manually by escaping the ampersand:http://example.org/?parameter=father%26sonHowever,
Uri.EscapeUriStringwill escape the percent character too, leading to a double encoding:http://example.org/?parameter=father%2526son
您有一个简单的 URI,如下所示:
http://example.org/Uri.EscapeUriString不会改变它。您决定手动编辑查询字符串而不考虑转义:
http://example.org/?key=two wordsUri.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
As you can see, using Uri.EscapeUriStringfor its intended purpose makes it impossible to use &as part of a key or value in a query string instead of as a separator between multiple key-value pairs.
如您所见,Uri.EscapeUriString用于其预期目的使其无法&用作查询字符串中的键或值的一部分,而不是用作多个键值对之间的分隔符。
This is because, in an attempt at making it suitable for escaping full URIs, it ignores reserved characters and only escapes characters that are neither reserved nor unreserved, which, BTW, is contrary to the documentation. This way you don't end up with something like http%3A%2F%2Fexample.org%2F, but you do end up with the issues illustrated above.
这是因为,为了使其适合转义完整 URI,它忽略了保留字符,只转义既不是保留也不是非保留的字符,顺便说一句,这与文档相反。这样你就不会得到类似的东西http%3A%2F%2Fexample.org%2F,但你最终会遇到上面说明的问题。
In the end, if your URI is valid, it does not need to be escaped to be passed as a parameter to the Uri construtor, and if it's not valid then calling Uri.EscapeUriStringisn't a magic solution either. Actually, it will work in many if not most cases, but it is by no means reliable.
最后,如果您的 URI 有效,则不需要对其进行转义以作为参数传递给 Uri 构造函数,如果无效,则调用Uri.EscapeUriString也不是一个神奇的解决方案。实际上,即使不是大多数情况,它也适用于许多情况,但它绝不可靠。
You should always construct your URLs and query strings by gathering the key-value pairs and percent-encoding and then concatenating them with the necessary separators. You can use Uri.EscapeDataStringfor this purpose, but not Uri.EscapeUriString, since it doesn't escape reserved characters, as mentioned above.
您应该始终通过收集键值对和百分比编码,然后将它们与必要的分隔符连接来构建您的 URL 和查询字符串。您可以Uri.EscapeDataString为此目的使用,但不能使用Uri.EscapeUriString,因为它不会转义保留字符,如上所述。
Only if you cannot do that, e.g. when dealing with user-provided URIs, does it make sense to use Uri.EscapeUriStringas a last resort. But the previously mentioned caveats apply – if the user-provided URI is ambiguous, the results may not be desirable.
只有当您不能这样做时,例如在处理用户提供的 URI 时,才将其Uri.EscapeUriString用作最后的手段。但是前面提到的警告适用 - 如果用户提供的 URI 不明确,结果可能不理想。
回答by Seth
The plus (+) characters can reveal a lot about the difference between these methods. In a simple URI, the plus character means "space". Consider querying Google for "happy cat":
加号 (+) 字符可以揭示很多关于这些方法之间差异的信息。在简单的 URI 中,加号表示“空格”。考虑在 Google 上查询“happy cat”:
That's a valid URI (try it), and EscapeUriStringwill not modify it.
这是一个有效的 URI(试试看),EscapeUriString不会修改它。
Now consider querying Google for "happy c++":
现在考虑向 Google 查询“happy c++”:
That's a valid URI (try it), but it produces a search for "happy c", because the two pluses are interpreted as spaces. To fix it, we can pass "happy c++" to EscapeDataStringand voila*:
这是一个有效的 URI(试试看),但它会搜索“happy c”,因为这两个加号被解释为空格。要修复它,我们可以将“happy c++”传递给EscapeDataStringvoila *:
*)The encoded data string is actually "happy%20c%2B%2B"; %20 is hex for the space character, and %2B is hex for the plus character.
*)编码后的数据串实际上是“happy%20c%2B%2B”;%20 是空格字符的十六进制,%2B 是加号字符的十六进制。
If you're using UriBuilderas you should be, then you'll only need EscapeDataStringto properly escape some of the components of your entire URI. @Livven's answer to this question further proves that there really is no reason to use EscapeUriString.
如果您UriBuilder按应有的方式使用,那么您只需要EscapeDataString正确转义整个 URI 的某些组件即可。@Livven 对这个问题的回答进一步证明确实没有理由使用EscapeUriString.
回答by Todd Menier
Comments in the sourceaddress the difference clearly. Why this info isn't brought forward via XML documentation comments is a mystery to me.
源代码中的注释清楚地解决了差异。为什么不通过 XML 文档注释提供此信息对我来说是个谜。
EscapeUriString:
转义字符串:
This method will escape any character that is not a reserved or unreserved character, including percent signs. Note that EscapeUriString will also do not escape a '#' sign.
此方法将转义任何非保留或非保留字符的字符,包括百分号。请注意, EscapeUriString 也不会转义“#”符号。
EscapeDataString:
转义数据字符串:
This method will escape any character that is not an unreserved character, including percent signs.
此方法将转义任何不是非保留字符的字符,包括百分号。
So the difference is in how they handle reservedcharacters. EscapeDataStringescapes them; EscapeUriStringdoes not.
所以区别在于它们如何处理保留字符。EscapeDataString逃脱他们;EscapeUriString才不是。
According to the RFC, the reserved characters are: :/?#[]@!$&'()*+,;=
根据RFC,保留字符是::/?#[]@!$&'()*+,;=
For completeness, the unreserved characters are alphanumeric and -._~
为完整起见,未保留的字符是字母数字和 -._~
Both methods escape characters that are neither reserved nor unreserved.
这两种方法都对既非保留也非非保留的字符进行转义。
I disagree with the general notionthat EscapeUriStringis evil. I think a method that escapes only illegalcharacters (such as spaces) and not reservedcharacters is useful. But it does have a quirk in how it handles the %character. Percent-encoded characters (%followed by 2 hex digits) are legalin a URI. I think EscapeUriStringwould be far more useful if it detected this pattern and avoided encoding %when it's immediately proceeded by 2 hex digits.
我不同意与一般观念认为EscapeUriString是邪恶的。我认为只转义非法字符(如空格)而不转义保留字符的方法很有用。但它在处理%角色方面确实有一个怪癖。百分比编码字符(%后跟 2 个十六进制数字)在 URI 中是合法的。我认为EscapeUriString如果它检测到这种模式并%在它立即进行 2 个十六进制数字时避免编码会更有用。
回答by Learning
A simple example
一个简单的例子
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
*/

