简体   繁体   English

Server.UrlEncode与HttpUtility.UrlEncode

[英]Server.UrlEncode vs. HttpUtility.UrlEncode

Server.UrlEncode和HttpUtility.UrlEncode之间有区别吗?

I had significant headaches with these methods before, I recommend you avoid any variant of UrlEncode , and instead use Uri.EscapeDataString - at least that one has a comprehensible behavior. 我之前对这些方法感到非常头痛, 我建议你避免使用UrlEncode任何变体,而是使用Uri.EscapeDataString - 至少那个具有可理解的行为。

Let's see... 让我们来看看...

HttpUtility.UrlEncode(" ") == "+" //breaks ASP.NET when used in paths, non-
                                  //standard, undocumented.
Uri.EscapeUriString("a?b=e") == "a?b=e" // makes sense, but rarely what you
                                        // want, since you still need to
                                        // escape special characters yourself

But my personal favorite has got to be HttpUtility.UrlPathEncode - this thing is really incomprehensible. 但我个人最喜欢的必须是HttpUtility.UrlPathEncode - 这件事真是难以理解。 It encodes: 它编码:

  • " " ==> "%20" “”==>“%20”
  • "100% true" ==> "100%%20true" (ok, your url is broken now) “100%true”==>“100 %% 20true”(好吧,你的网址现在坏了)
  • "test A.aspx#anchor B" ==> "test%20A.aspx #anchor%20B " “test A.aspx#anchor B”==>“test%20A.aspx #anchor%20B
  • "test A.aspx?hmm#anchor B" ==> "test%20A.aspx?hmm #anchor B " ( note the difference with the previous escape sequence! ) “测试A.aspx?hmm#anchor B”==>“test%20A.aspx?hmm #anchor B ”( 注意与前一个转义序列的区别!

It also has the lovelily specific MSDN documentation "Encodes the path portion of a URL string for reliable HTTP transmission from the Web server to a client." 它还具有可爱的MSDN文档“对URL字符串的路径部分进行编码,以便从Web服务器向客户端进行可靠的HTTP传输”。 - without actually explaining what it does. - 没有实际解释它的作用。 You are less likely to shoot yourself in the foot with an Uzi... 你不太可能用Uzi射击自己的脚...

In short, stick to Uri.EscapeDataString . 简而言之,坚持使用Uri.EscapeDataString

HttpServerUtility.UrlEncode will use HttpUtility.UrlEncode internally. HttpServerUtility.UrlEncodeHttpUtility.UrlEncode内部使用HttpUtility.UrlEncode There is no specific difference. 没有具体的区别。 The reason for existence of Server.UrlEncode is compatibility with classic ASP. Server.UrlEncode存在的Server.UrlEncode是与传统ASP的兼容性。

Fast-forward almost 9 years since this was first asked, and in the world of .NET Core and .NET Standard, it seems the most common options we have for URL-encoding are WebUtility.UrlEncode (under System.Net ) and Uri.EscapeDataString . 自从第一次提出这个问题以来,快进了近9年,在.NET Core和.NET Standard的世界中,我们对URL编码最常见的选择似乎是WebUtility.UrlEncode (在System.Net下)和Uri。 EscapeDataString Judging by the most popular answer here and elsewhere, Uri.EscapeDataString appears to be preferable. 从这里和其他地方最流行的答案来看, Uri.EscapeDataString似乎更可取。 But is it? 但是吗? I did some analysis to understand the differences and here's what I came up with: 我做了一些分析以了解差异,这是我想出的:

  • WebUtility.UrlEncode encodes space as + ; WebUtility.UrlEncode将空间编码为+ ; Uri.EscapeDataString encodes it as %20 . Uri.EscapeDataString将其编码为%20
  • Uri.EscapeDataString percent-encodes ! Uri.EscapeDataString百分比编码! , ( , ) , and * ; ()* ; WebUtility.UrlEncode does not. WebUtility.UrlEncode没有。
  • WebUtility.UrlEncode percent-encodes ~ ; WebUtility.UrlEncode百分比编码~ ; Uri.EscapeDataString does not. Uri.EscapeDataString没有。
  • Uri.EscapeDataString throws a UriFormatException on strings longer than 65,520 characters; Uri.EscapeDataString抛出一个UriFormatException的字符串长度超过65,520个字符长; WebUtility.UrlEncode does not. WebUtility.UrlEncode没有。 ( A more common problem than you might think, particularly when dealing with URL-encoded form data .) 比您想象的更常见的问题,特别是在处理URL编码的表单数据时 。)
  • Uri.EscapeDataString throws a UriFormatException on the high surrogate characters ; Uri.EscapeDataString高代理字符抛出UriFormatException ; WebUtility.UrlEncode does not. WebUtility.UrlEncode没有。 (That's a UTF-16 thing, probably a lot less common.) (这是一个UTF-16的东西,可能不太常见。)

For URL-encoding purposes, characters fit into one of 3 categories: unreserved (legal in a URL); 对于URL编码目的,字符符合以下三个类别之一:未保留(URL中合法); reserved (legal in but has special meaning, so you might want to encode it); 保留(合法但具有特殊含义,因此您可能希望对其进行编码); and everything else (must always be encoded). 和其他一切(必须始终编码)。

According to the RFC , the reserved characters are: :/?#[]@!$&'()*+,;= 根据RFC ,保留字符是:: :/?#[]@!$&'()*+,;=

And the unreserved characters are alphanumeric and -._~ 并且未保留的字符是字母数字和-._~

The Verdict 判决

Uri.EscapeDataString clearly defines its mission: %-encode all reserved and illegal characters. Uri.EscapeDataString明确定义了它的任务:% - 编码所有保留和非法字符。 WebUtility.UrlEncode is more ambiguous in both definition and implementation. WebUtility.UrlEncode在定义和实现方面都更加模糊。 Oddly, it encodes some reserved characters but not others (why parentheses and not brackets??), and stranger still it encodes that innocently unreserved ~ character. 奇怪的是,它编码的一些保留字符而不是其他(为什么括号,而不是括号?),并且奇怪的是它编码傻傻未保留~字符。

Therefore, I concur with the popular advice - use Uri.EscapeDataString when possible, and understand that reserved characters like / and ? 因此,我同意流行的建议 - 尽可能使用Uri.EscapeDataString ,并了解保留字符,如/? will get encoded. 将被编码。 If you need to deal with potentially large strings, particularly with URL-encoded form content, you'll need to either fall back on WebUtility.UrlEncode and accept its quirks, or otherwise work around the problem. 如果你需要处理潜在的大字符串,特别是URL编码的表单内容,你需要依靠WebUtility.UrlEncode并接受它的怪癖,或以其他方式解决问题。


EDIT: I've attempted to rectify ALL of the quirks mentioned above in Flurl via the Url.Encode , Url.EncodeIllegalCharacters , and Url.Decode static methods. 编辑:试图通过Url.EncodeUrl.EncodeIllegalCharactersUrl.Decode静态方法纠正Flurl中上面提到的所有怪癖。 These are in the core package (which is tiny and doesn't include all the HTTP stuff), or feel free to rip them from the source. 这些是在核心包中 (它很小,并不包括所有的HTTP内容),或者可以随意从源代码中删除它们。 I welcome any comments/feedback you have on these. 我欢迎您对这些提出任何意见/反馈。


Here's the code I used to discover which characters are encoded differently: 这是我用来发现哪些字符编码方式不同的代码:

var diffs =
    from i in Enumerable.Range(0, char.MaxValue + 1)
    let c = (char)i
    where !char.IsHighSurrogate(c)
    let diff = new {
        Original = c,
        UrlEncode = WebUtility.UrlEncode(c.ToString()),
        EscapeDataString = Uri.EscapeDataString(c.ToString()),
    }
    where diff.UrlEncode != diff.EscapeDataString
    select diff;

foreach (var diff in diffs)
    Console.WriteLine($"{diff.Original}\t{diff.UrlEncode}\t{diff.EscapeDataString}");

Keep in mind that you probably shouldn't be using either one of those methods. 请记住,您可能不应该使用这些方法中的任何一种。 Microsoft's Anti-Cross Site Scripting Library includes replacements for HttpUtility.UrlEncode and HttpUtility.HtmlEncode that are both more standards-compliant, and more secure. Microsoft的Anti-Cross Site Scripting Library包括HttpUtility.UrlEncodeHttpUtility.HtmlEncode替代品,它们更符合标准,更安全。 As a bonus, you get a JavaScriptEncode method as well. 作为奖励,您还可以获得JavaScriptEncode方法。

Server.UrlEncode() is there to provide backward compatibility with Classic ASP, Server.UrlEncode()用于向后兼容Classic ASP,

Server.UrlEncode(str);

Is equivalent to: 相当于:

HttpUtility.UrlEncode(str, Response.ContentEncoding);

同样, Server.UrlEncode()调用HttpUtility.UrlEncode()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM