Como você UrlEncode sem usar o System.Web?


310

Estou tentando escrever um aplicativo cliente do Windows que chama um site para obter dados. Para manter a instalação no mínimo, estou tentando usar apenas dlls no .NET Framework Client Profile . O problema é que eu preciso UrlEncode alguns parâmetros, existe uma maneira fácil de fazer isso sem importar o System.Web.dll, que não faz parte do perfil do cliente?


Você poderia mostrar como está realizando a chamada para o site? Talvez haja algo que possa ser feito lá.
— Darin Dimitrov

Por curiosidade, como você chama um site para obter dados sem usar o System.Web?
— Patrick McDonald

@ Patrick, ele provavelmente está usando WebRequestou WebClient. Essa é a razão pela qual perguntei sobre esse código específico, porque há coisas que podem ser feitas sobre dados de codificação de URL corretamente.
— Darin Dimitrov

1
Estou usando um objeto System.Net.WebRequest. Então eu chamo GetRequestStream e escrevo meus parâmetros Post no fluxo. Também defino o ContentType como "application / x-www-form-urlencoded".
— Martin Brown

1
É claro que isso se aplicaria igualmente bem se eu estivesse executando uma solicitação GET e anexando os parâmetros ao URL.
— Martin Brown

Respostas:


317

System.Uri.EscapeUriString() pode ser problemático com certos caracteres, para mim era um sinal de número / libra '#' na string.

Se esse é um problema para você, tente:

System.Uri.EscapeDataString() //Works excellent with individual values

Aqui está uma resposta da pergunta SO que explica a diferença:

Qual é a diferença entre EscapeUriString e EscapeDataString?

e recomenda usar Uri.EscapeDataString()em qualquer aspecto.


1
Falso: blogs.msdn.com/b/yangxind/archive/2006/11/09/… Você terá problemas com sinais de adição, pois eles não serão codificados.
— 22812 Chris Weber

7
Essa postagem do blog é um pouco antiga e eu apenas "Uri escapei" de uma URL completa e todos os espaços se tornaram% 20, então acho que eles a corrigiram. Estou usando o .Net 4.5.
— Rodi

O EscapeDataString também não suporta seqüências muito longas se você estiver preparando dados para uma operação POST. stackoverflow.com/questions/6695208/…
— Bron Davies

Uri.EscapeUriStringé realmente muito problemático e não deve ser usado, pois tenta fazer algo (escapando de URIs completos) que é realmente impossível de fazer de forma consistente. Consulte esta resposta para obter uma explicação detalhada.
— Livven

Também um caractere '' Space.
— Waqas Shabbir

252

No uso do .Net 4.5+ WebUtility

Apenas para formatação, estou enviando isso como resposta.

Não foi possível encontrar bons exemplos comparando-os assim:

string testString = "http://test# space 123/text?var=val&another=two";
Console.WriteLine("UrlEncode:         " + System.Web.HttpUtility.UrlEncode(testString));
Console.WriteLine("EscapeUriString:   " + Uri.EscapeUriString(testString));
Console.WriteLine("EscapeDataString:  " + Uri.EscapeDataString(testString));
Console.WriteLine("EscapeDataReplace: " + Uri.EscapeDataString(testString).Replace("%20", "+"));

Console.WriteLine("HtmlEncode:        " + System.Web.HttpUtility.HtmlEncode(testString));
Console.WriteLine("UrlPathEncode:     " + System.Web.HttpUtility.UrlPathEncode(testString));

//.Net 4.0+
Console.WriteLine("WebUtility.HtmlEncode: " + WebUtility.HtmlEncode(testString));
//.Net 4.5+
Console.WriteLine("WebUtility.UrlEncode:  " + WebUtility.UrlEncode(testString));

Saídas:

UrlEncode:             http%3a%2f%2ftest%23+space+123%2ftext%3fvar%3dval%26another%3dtwo
EscapeUriString:       http://test#%20space%20123/text?var=val&another=two
EscapeDataString:      http%3A%2F%2Ftest%23%20space%20123%2Ftext%3Fvar%3Dval%26another%3Dtwo
EscapeDataReplace:     http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

HtmlEncode:            http://test# space 123/text?var=val&another=two
UrlPathEncode:         http://test#%20space%20123/text?var=val&another=two

//.Net 4.0+
WebUtility.HtmlEncode: http://test# space 123/text?var=val&another=two
//.Net 4.5+
WebUtility.UrlEncode:  http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

No uso do .Net 4.5+ WebUtility.UrlEncode

Isso parece replicar HttpUtility.UrlEncode(pré-v4.0) para os caracteres mais comuns:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Nota: EscapeUriStringmanterá uma string uri válida, o que fará com que use o máximo de caracteres de texto sem formatação possível.

Consulte esta resposta para obter uma tabela comparando as várias codificações:
https://stackoverflow.com/a/11236038/555798

Quebras de linha Todos eles listados aqui (exceto HttpUtility.HtmlEncode) serão convertidos "\n\r"em %0a%0dou%0A%0D

Sinta-se à vontade para editar isso e adicionar novos caracteres à minha string de teste, ou deixe-os nos comentários e eu os editarei.


No meu caso eu tive que usar EscapeDataString, em vez de EscapeUriStringcomo fomos codificação retornos de carro e alimentações de linha e estes exigido o mais agressivo escapando realizada porEscapeDataString
— David O'Meara

1
mais exemplos, você pode fornecer seus próprios casos de teste, se desejar. Aqui está um exemplo de como executá-lo e os outros métodos de codificação que mostram diferenças dotnetfiddle.net/12IFw1
— Maslow

3
WebUtility.UrlEncode () e WebUtility.UrlDecode () são 4.5+. Eles não existem no 4.0.
— Derek Kalweit

O msdn diz: "Plataforma Universal do Windows: disponível desde a versão 4.5, .NET Framework: disponível desde a versão 4.0" ...
— Thymine

54

Você pode usar

Uri.EscapeUriString (consulte http://msdn.microsoft.com/en-us/library/system.uri.escapeuristring.aspx )


Existe uma diferença entre isso e EscapeDataString?
— Martin Brown

3
Você deseja usar o EscapeUriString. O EscapeUriString vai tentar codificar toda a url (incluir http: // parte), enquanto EscapeUriString entende que partes realmente deve ser codificado
— Matthew Manela

1
Entendo, então, neste caso, eu provavelmente desejaria EscapeDataString, pois posso passar uma URL como parâmetro get. Estou anexando a um URL nesta instância.
— Martin Brown

5
@MatthewManela eu tenho certeza que o seu comentário OCT1 deve ler O EscapeDataString vai tentar codificar ...
— Maslow

Não use Uri.EscapeUriString. Ele não "entende" quais partes devem ser codificadas, é apenas uma tentativa equivocada de fazer algo (escapando dos URIs completos) que é realmente impossível fazer de forma consistente. Veja esta resposta para uma explicação detalhada.
— Livven

20

As respostas aqui são muito boas, mas ainda insuficientes para mim.

Eu escrevi um pequeno laço que compara Uri.EscapeUriStringcom Uri.EscapeDataStringpara todos os caracteres de 0 a 255.

NOTA: Ambas as funções possuem a inteligência incorporada de que caracteres acima de 0x80 são codificados primeiro em UTF-8 e depois codificados em porcentagem.

Aqui está o resultado:

******* Different *******

'#' -> Uri "#" Data "%23"
'$' -> Uri "$" Data "%24"
'&' -> Uri "&" Data "%26"
'+' -> Uri "+" Data "%2B"
',' -> Uri "," Data "%2C"
'/' -> Uri "/" Data "%2F"
':' -> Uri ":" Data "%3A"
';' -> Uri ";" Data "%3B"
'=' -> Uri "=" Data "%3D"
'?' -> Uri "?" Data "%3F"
'@' -> Uri "@" Data "%40"


******* Not escaped *******

'!' -> Uri "!" Data "!"
''' -> Uri "'" Data "'"
'(' -> Uri "(" Data "("
')' -> Uri ")" Data ")"
'*' -> Uri "*" Data "*"
'-' -> Uri "-" Data "-"
'.' -> Uri "." Data "."
'_' -> Uri "_" Data "_"
'~' -> Uri "~" Data "~"

'0' -> Uri "0" Data "0"
.....
'9' -> Uri "9" Data "9"

'A' -> Uri "A" Data "A"
......
'Z' -> Uri "Z" Data "Z"

'a' -> Uri "a" Data "a"
.....
'z' -> Uri "z" Data "z"

******* UTF 8 *******

.....
'Ò' -> Uri "%C3%92" Data "%C3%92"
'Ó' -> Uri "%C3%93" Data "%C3%93"
'Ô' -> Uri "%C3%94" Data "%C3%94"
'Õ' -> Uri "%C3%95" Data "%C3%95"
'Ö' -> Uri "%C3%96" Data "%C3%96"
.....

EscapeUriStringdeve ser usado para codificar URLs, enquanto EscapeDataStringdeve ser usado para codificar, por exemplo, o conteúdo de um Cookie, porque os dados do Cookie não devem conter os caracteres '='e ';'.


boa análise e análise aqui, muito útil. se alguém tem ou sabe de benchmarks de desempenho (comparando todos os três métodos), que também seria bom ver
— Shaun Wilson

Essa é uma boa análise e o que você deve levar em consideração é que você não deve usá-lo Uri.EscapeUriString, porque é impossível fazer escape de URIs completos de forma consistente. Veja esta resposta para uma explicação detalhada.
— Livven

16

Há uma versão utilizável do perfil do cliente, classe System.Net.WebUtility, presente no perfil do cliente System.dll. Aqui está o link do MSDN:

WebUtility


Gostaria de observar que a página de ajuda para essa classe diz especificamente "Fornece métodos para codificar e decodificar URLs ao processar solicitações da Web". então pode ser que eles não tenham nomeado bem os métodos.
— James White

Bom ponto, digamos, por que você não vota em um irmão;) esse voto negativo me assombra há 2 anos! JK ... mas sinceramente isso é provavelmente por isso que eu postei o link, lamentável que eu tomar uma batida reputação de erros em documentos da Microsoft ...
— Sprague

11
Parece que UrlEncode e UrlDecode foram adicionados apenas ao WebUtility na versão 4.5 do .Net.
— Martin Brown

8

Aqui está um exemplo de envio de uma solicitação POST que codifica corretamente os parâmetros usando o application/x-www-form-urlencodedtipo de conteúdo:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "param1", "value1" },
        { "param2", "value2" },
    };
    var result = client.UploadValues("http://foo.com", values);
}


-3
System.Net.WebUtility.HtmlDecode

A classe WebUtility fornece métodos para codificar e decodificar URLs ao processar solicitações da Web. Ele faz a mesma coisa que HttpUtility mas é fora do namespace System.Web
— Alexandru Aliu

3
Está errado porque HtmlDecodes e não UrlEncode como a pergunta. Mesmo HtmlEncode estaria errado, pois a codificação HTML é diferente da codificação de URL.
— Martin Brown
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.