Server.UrlEncode vs. HttpUtility.UrlEncode

177

Existe uma diferença entre Server.UrlEncode e HttpUtility.UrlEncode?

Manu
fonte

Respostas:

133

HttpServerUtility.UrlEncodeusará HttpUtility.UrlEncodeinternamente. Não há diferença específica. A razão da existência de Server.UrlEncodeé compatibilidade com o ASP clássico.

Mehrdad Afshari
fonte
3
Quanto ao que é escapado. Internamente, chama essa função referenceource.microsoft.com/#System/net/System/Net/…
Jeff
Para os leitores: Veja a resposta de Joel Muller abaixo. Essa é a maneira mais eficaz de codificar URL: stackoverflow.com/a/603962/190476
Sudhanshu Mishra 2/16/16
264

Eu tive dores de cabeça significativas com esses métodos antes, eu recomendo que você evite qualquer variante UrlEncodee useUri.EscapeDataString - pelo menos esse tenha um comportamento compreensível.

Vamos ver...

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

Mas meu favorito pessoal deve ser o HttpUtility.UrlPathEncode - isso é realmente incompreensível. Codifica:

  • "" ==> "% 20"
  • "100% verdadeiro" ==> "100 %% 20 verdadeiro" (ok, seu URL está quebrado agora)
  • "teste A.aspx # âncora B" ==> "teste% 20A.aspx # âncora% 20B "
  • "test A.aspx? hmm # âncora B" ==> "test% 20A.aspx? hmm #anchor B " ( notar a diferença com a seqüência de escape anterior! )

Ele também possui a documentação específica do MSDN, "Codifica a parte do caminho de uma string de URL para uma transmissão HTTP confiável do servidor da Web para um cliente". - sem realmente explicar o que faz. É menos provável que você atinja seu pé com uma Uzi ...

Em suma, atenha-se ao Uri.EscapeDataString .

Eamon Nerbonne
fonte
4
E, infelizmente, isso ainda não funciona ao fazer solicitações HTTP em alguns servidores da Web - Uri.EscapeDataString () não codifica "!" ou "", que difere da forma como a maioria das implementações do navegador de escape () trabalho ...
Chris R. Donnelly
6
! e 'caracteres não devem ser codificados; mas se um servidor da web de buggy exigir isso, é fácil contornar isso. Evite a função de escape do javascript - é inerentemente incorreta (impossível rodar, por exemplo). Veja xkr.us/articles/javascript/encode-compare - mas em resumo; você pode usar encodeUriComponent (), que se comporta de maneira semelhante a EscapeDataString - codifica previsivelmente e reversivelmente uma string e também não codifica! e 'caracteres.
Eamon Nerbonne
2
Isso é antigo, mas a pergunta foi colocada na primeira página, então ... A parte do caminho de uma string de URL é a parte entre o domínio e o? ou # em um URL.
Powerlord 23/12/2009
2
@ Tim: pode haver vários ?e quem pode dizer quais devem ser codificados e quais servem como separadores? Quanto ao espaço: nos dois casos, o espaço está no hash; portanto, a presença ou ausência de um fragmento de consulta não deve importar. E, finalmente, é indesculpável corromper um Uri, como no segundo exemplo, contendo um%. O UrlPathEncodemétodo é simples e nunca deve ser usado.
Eamon Nerbonne
1
Acho que minha resposta em stackoverflow.com/a/13993486/237091 pode lançar um pouco de luz sobre o uso pretendido de UrlEncode / UrlPathEncode.
Scott Stafford
60

Avançando quase 9 anos desde que isso foi solicitado pela primeira vez, e no mundo do .NET Core e .NET Standard, parece que as opções mais comuns que temos para codificação de URL são WebUtility.UrlEncode (under System.Net) e Uri.EscapeDataString . A julgar pela resposta mais popular aqui e em outros lugares, Uri.EscapeDataString parece ser preferível. Mas é isso? Eu fiz algumas análises para entender as diferenças e aqui está o que eu vim com:

Para fins de codificação de URL, os caracteres se enquadram em uma de três categorias: sem reserva (legal em uma URL); reservado (legal, mas tem um significado especial, então você pode querer codificá-lo); e tudo o mais (sempre deve ser codificado).

De acordo com a RFC , os caracteres reservados são::/?#[]@!$&'()*+,;=

E os caracteres não reservados são alfanuméricos e -._~

O veredito

Uri.EscapeDataString define claramente sua missão:%-codode todos os caracteres reservados e ilegais. WebUtility.UrlEncode é mais ambíguo na definição e na implementação. Estranhamente, ele codifica alguns caracteres reservados, mas não outros (por que parênteses e não parênteses?), E, ​​ainda mais estranho, codifica esse ~personagem inocentemente não reservado .

Portanto, concordo com o conselho popular - use Uri.EscapeDataString quando possível e entenda que caracteres reservados gostam /e ?serão codificados. Se você precisar lidar com cadeias potencialmente grandes, principalmente com conteúdo de formulário codificado por URL, precisará usar o WebUtility.UrlEncode e aceitar suas peculiaridades ou solucionar o problema.


EDIT: Eu tenho tentado retificar TODAS as peculiaridades mencionados acima em Flurl via Url.Encode, Url.EncodeIllegalCharacterse Url.Decodemétodos estáticos. Eles estão no pacote principal (que é pequeno e não inclui todo o material HTTP), ou fique à vontade para extraí-los da fonte. Congratulo-me com quaisquer comentários / feedback que você tem sobre estes.


Aqui está o código que eu usei para descobrir quais caracteres são codificados de maneira diferente:

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}");
Todd Menier
fonte
2
Isto é brilhante!
Jorge Aguirre
1
Excelente trabalho na verificação da solução sugerida na moderna estrutura .net.
Neowizard
Deve-se mencionar que existem algumas diferenças entre o WebUtility e o HttpUtility . WebUtility está usando maiúsculas e HttpUtility está usando minúsculas para entidades hexa. Além disso, o HttpUtility não foi incluído nas versões antigas de subconjuntos do .NET Framework "Client Profile". O WebUtility está disponível no .NET Framework 4.0.
Tibx
28

Lembre-se de que você provavelmente não deveria estar usando nenhum desses métodos. A Biblioteca de scripts anti-site da Microsoft inclui substituições HttpUtility.UrlEncodee HttpUtility.HtmlEncodeque são mais compatíveis com os padrões e mais seguras. Como bônus, você recebe um JavaScriptEncodemétodo também.

Joel Mueller
fonte
Depois de ler a documentação e as perguntas frequentes no link fornecido, acredito que esta resposta seja a melhor e mais segura maneira de codificar dados! Muito obrigado por compartilhar isso!
Sudhanshu Mishra 02/04
O link não funciona mais. Quais são os métodos de substituição?
Edward Brey
@EdwardBrey Esta é a versão mais recente do Anti-Cross biblioteca site scripting: microsoft.com/en-au/download/details.aspx?id=28589
Sudhanshu Mishra
11

Server.UrlEncode () existe para fornecer compatibilidade com o ASP clássico,

Server.UrlEncode(str);

É equivalente a:

HttpUtility.UrlEncode(str, Response.ContentEncoding);
CMS
fonte
5

O mesmo, Server.UrlEncode()chamaHttpUtility.UrlEncode()

andleer
fonte