¿Cómo se codifica UrlEncode sin usar System.Web?

310

Estoy tratando de escribir una aplicación cliente de Windows que llame a un sitio web para obtener datos. Para mantener la instalación al mínimo, estoy intentando usar solo dlls en .NET Framework Client Profile . El problema es que necesito UrlEncode algunos parámetros, ¿hay una manera fácil de hacerlo sin importar System.Web.dll que no es parte del Client Pofile?

Martin Brown
fuente
¿Podría mostrar cómo realiza la llamada al sitio web? Tal vez hay algo que se puede hacer allí.
Darin Dimitrov
Por curiosidad, ¿cómo se llama a un sitio web para obtener datos sin usar System.Web?
Patrick McDonald el
@Patrick, probablemente esté usando WebRequesto WebClient. Esa es la razón por la que pregunté sobre este código en particular porque hay cosas que se pueden hacer para codificar correctamente los datos de URL.
Darin Dimitrov
1
Estoy usando un objeto System.Net.WebRequest. Luego llamo a GetRequestStream y escribo mis parámetros de publicación en la secuencia. También configuré ContentType en "application / x-www-form-urlencoded".
Martin Brown
1
Por supuesto, esto también se aplicaría si estuviera realizando una solicitud GET y agregando los parámetros a la URL.
Martin Brown

Respuestas:

317

System.Uri.EscapeUriString() puede ser problemático con ciertos caracteres, para mí fue un signo de número / libra '#' en la cadena.

Si eso es un problema para usted, intente:

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

Aquí hay una respuesta de pregunta SO que explica la diferencia:

¿Cuál es la diferencia entre EscapeUriString y EscapeDataString?

y recomienda usar Uri.EscapeDataString()en cualquier aspecto.

ToddBFisher
fuente
1
Falso: blogs.msdn.com/b/yangxind/archive/2006/11/09 /... Tendrá problemas con los signos más, ya que no estarán sin codificar.
Chris Weber
77
Esa publicación de blog es un poco vieja y solo tengo "Uri Escaped" una url completa y todos los espacios se han convertido en% 20, así que creo que lo arreglaron. Estoy usando .Net 4.5.
Rodi
EscapeDataString tampoco admite cadenas muy largas si está preparando datos para una operación POST. stackoverflow.com/questions/6695208/…
Bron Davies
Uri.EscapeUriStringes realmente muy problemático y no debe usarse, ya que trata de hacer algo (escapar de los URI completos) que en realidad es imposible de hacer de manera consistente. Consulte esta respuesta para obtener una explicación detallada.
Livven
También un personaje espacial.
Waqas Shabbir
252

En .Net 4.5+ uso WebUtility

Solo por formatear estoy enviando esto como respuesta.

No pude encontrar buenos ejemplos comparándolos así:

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));

Salidas:

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

En .Net 4.5+ uso WebUtility.UrlEncode

Esto parece replicarse HttpUtility.UrlEncode(anterior a la v4.0) para los caracteres más comunes:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Nota: EscapeUriStringmantendrá una cadena uri válida, lo que hace que use tantos caracteres de texto sin formato como sea posible.

Vea esta respuesta para una tabla que compara las diversas codificaciones:
https://stackoverflow.com/a/11236038/555798

Saltos de línea Todos los enumerados aquí (que no sean HttpUtility.HtmlEncode) se convertirán "\n\r"en %0a%0do%0A%0D

Siéntase libre de editar esto y agregar nuevos caracteres a mi cadena de prueba, o dejarlos en los comentarios y lo editaré.

Timina
fuente
En mi caso, tuve que usar EscapeDataStringen lugar de EscapeUriStringcomo estábamos codificación de retornos de carro y avances de línea y éstos se requiere el más agresivo escape que realizado porEscapeDataString
David O'Meara
1
más ejemplos, puede proporcionar sus propios casos de prueba si lo desea. Aquí hay una muestra de cómo
Maslow
3
WebUtility.UrlEncode () y WebUtility.UrlDecode () son 4.5+. No existen en 4.0.
Derek Kalweit
El msdn dice: "Plataforma universal de Windows: disponible desde 4.5, .NET Framework: disponible desde 4.0" ...
Thymine
54

Puedes usar

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

Matthew Manela
fuente
¿Hay alguna diferencia entre esto y EscapeDataString?
Martin Brown
3
Desea usar EscapeUriString. EscapeUriString intentará codificar toda la url (incluya http: // part) mientras EscapeUriString entiende qué partes deben codificarse realmente
Matthew Manela,
1
Ya veo, así que en este caso probablemente querría EscapeDataString, ya que es posible que quiera pasar una URL como parámetro de obtención. Estoy anexando una URL en esta instancia.
Martin Brown
55
@MatthewManela Estoy bastante seguro de que tu comentario del 1 de octubre
Maslow
No utilice Uri.EscapeUriString. No "comprende" qué partes deben codificarse, es solo un intento equivocado de hacer algo (escapar de los URI completos) que en realidad es imposible de hacer de manera consistente. Vea esta respuesta para una explicación detallada.
Livven
20

Las respuestas aquí son muy buenas, pero aún son insuficientes para mí.

Escribí un pequeño bucle que se compara Uri.EscapeUriStringcon Uri.EscapeDataStringtodos los caracteres del 0 al 255.

NOTA: Ambas funciones tienen la inteligencia incorporada de que los caracteres superiores a 0x80 se codifican primero con UTF-8 y luego con un porcentaje.

Aquí está el 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"
.....

EscapeUriStringdebe usarse para codificar URL, mientras EscapeDataStringque debe usarse para codificar, por ejemplo, el contenido de una Cookie, porque los datos de Cookie no deben contener los caracteres reservados '='y ';'.

Elmue
fuente
Buen análisis y desglose aquí, muy útil. si alguien tiene o conoce los puntos de referencia de rendimiento (comparando los tres métodos), eso también sería agradable de ver
Shaun Wilson el
Este es un buen análisis y la conclusión es que no debe usarlo Uri.EscapeUriString, porque escapar de los URI completos es imposible de hacer de manera consistente. Vea esta respuesta para una explicación detallada.
Livven
16

Hay una versión utilizable del perfil del cliente, clase System.Net.WebUtility, presente en el perfil del cliente System.dll. Aquí está el enlace de MSDN:

WebUtility

Sprague
fuente
Me gustaría señalar que la página de ayuda para esa clase dice específicamente "Proporciona métodos para codificar y decodificar URL cuando se procesan solicitudes web". así que podría ser que no nombraron bien los métodos.
James White
Buen punto, digamos, ¿por qué no votas a un hermano?) ¡Este voto negativo me ha estado persiguiendo durante 2 años! JK ... pero la verdad es que eso es probablemente por eso que envió el enlace, desafortunado que tomo un golpe reputación de errores en documentos de Microsoft ...
Sprague
11
Parece que UrlEncode y UrlDecode solo se agregaron a WebUtility en la versión 4.5 de .Net.
Martin Brown
8

Aquí hay un ejemplo de envío de una solicitud POST que codifica correctamente los parámetros utilizando el application/x-www-form-urlencodedtipo de contenido:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "param1", "value1" },
        { "param2", "value2" },
    };
    var result = client.UploadValues("http://foo.com", values);
}
Darin Dimitrov
fuente
-3
System.Net.WebUtility.HtmlDecode
usuario3105093
fuente
La clase WebUtility proporciona métodos para codificar y decodificar URL al procesar solicitudes web. Hace lo mismo que HttpUtility pero está fuera del sistema. Espacio de nombres web
Alexandru Aliu
3
Está mal porque HtmlDecodes y no codifica UrlEncode como la pregunta formulada. Incluso HtmlEncode estaría mal ya que la codificación HTML es diferente a la codificación URL.
Martin Brown