Respuestas:
Úselo EscapeDataString
siempre (para obtener más información sobre por qué, consulte la respuesta de Livven a continuación)
Editar : se eliminó el enlace muerto sobre cómo difieren los dos en la codificación
URLEncode
).
No encontré las respuestas existentes satisfactorias, así que decidí profundizar un poco más para resolver este problema. Sorprendentemente, la respuesta es muy simple:
No hay (casi *) ninguna razón válida para usarla Uri.EscapeUriString
. Si necesita codificar en porcentaje una cadena, use siempre Uri.EscapeDataString
.
* Vea el último párrafo para un caso de uso válido.
¿Por qué es esto? De acuerdo con la documentación :
Use el método EscapeUriString para preparar una cadena de URI sin escape para que sea un parámetro para el constructor de Uri.
Esto realmente no tiene sentido. De acuerdo con RFC 2396 :
Un URI siempre está en forma de "escape", ya que escapar o escapar de un URI completo podría cambiar su semántica.
Si bien el RFC citado ha quedado obsoleto por RFC 3986 , el punto sigue en pie. Vamos a verificarlo mirando algunos ejemplos concretos:
Tienes un URI simple, como este:
http://example.org/
Uri.EscapeUriString
No lo cambiará.
Decide editar manualmente la cadena de consulta sin tener en cuenta el escape:
http://example.org/?key=two words
Uri.EscapeUriString
(correctamente) escapará del espacio por ti:
http://example.org/?key=two%20words
Decide editar manualmente la cadena de consulta aún más:
http://example.org/?parameter=father&son
Sin embargo, esta cadena no cambia Uri.EscapeUriString
, ya que asume el ampers y significa el inicio de otro par clave-valor. Esto puede o no ser lo que pretendía.
Decide que, de hecho, desea que sea el key
parámetro father&son
, por lo que arregla la URL anterior manualmente escapando del signo y:
http://example.org/?parameter=father%26son
Sin embargo, Uri.EscapeUriString
también escapará al carácter de porcentaje, lo que conducirá a una doble codificación:
http://example.org/?parameter=father%2526son
Como puede ver, el uso Uri.EscapeUriString
para su propósito previsto hace que sea imposible usarlo &
como parte de una clave o valor en una cadena de consulta en lugar de como un separador entre múltiples pares clave-valor.
Esto se debe a que, en un intento de hacerlo adecuado para escapar de los URI completos, ignora los caracteres reservados y solo escapa a los caracteres que no están reservados ni no reservados, lo que, por cierto, es contrario a la documentación . De esta manera, no terminas con algo como esto http%3A%2F%2Fexample.org%2F
, pero sí terminas con los problemas ilustrados anteriormente.
Al final, si su URI es válido, no necesita escapar para pasarlo como un parámetro al constructor de Uri, y si no es válido, llamar Uri.EscapeUriString
tampoco es una solución mágica. En realidad, funcionará en muchos, si no en la mayoría de los casos, pero de ninguna manera es confiable.
Siempre debe construir sus URL y cadenas de consulta reuniendo los pares clave-valor y la codificación porcentual y luego concatenándolos con los separadores necesarios. Puede usar Uri.EscapeDataString
para este propósito, pero no Uri.EscapeUriString
, ya que no escapa a los caracteres reservados, como se mencionó anteriormente.
Solo si no puede hacerlo, por ejemplo, cuando se trata de URI proporcionados por el usuario, tiene sentido usarlo Uri.EscapeUriString
como último recurso. Pero se aplican las advertencias mencionadas anteriormente: si el URI proporcionado por el usuario es ambiguo, los resultados pueden no ser deseables.
encodeURI
/ Uri.EscapeUriString
no se necesita con tanta frecuencia como encodeURIComponent
/ Uri.EscapeDataString
(ya que cuando se trata de url ciegos que deben usarse en un contexto uri), pero eso no significa que no tenga su lugar.
Los caracteres más (+) pueden revelar mucho sobre la diferencia entre estos métodos. En un URI simple, el carácter más significa "espacio". Considere consultar a Google para "gato feliz":
Es un URI válido (pruébelo) y EscapeUriString
no lo modificará.
Ahora considere consultar en Google "happy c ++":
Es un URI válido (pruébelo), pero produce una búsqueda de "happy c", porque las dos ventajas se interpretan como espacios. Para solucionarlo, podemos pasar "happy c ++" a EscapeDataString
y voila * :
*) La cadena de datos codificada es en realidad "feliz% 20c% 2B% 2B"; % 20 es hexadecimal para el carácter de espacio, y% 2B es hexadecimal para el carácter más.
Si está utilizando UriBuilder
como debería, entonces solo necesitará EscapeDataString
escapar adecuadamente de algunos de los componentes de su URI completo. La respuesta de @ Livven a esta pregunta demuestra que realmente no hay razón para usar EscapeUriString
.
"https://www.google.com/?q=happy c++"
? Parece que necesito dividirme manualmente en "?", ¿O hay una mejor manera?
EscapeDataString
. Si la URL que proporcionó es la URL real, entonces sí desea dividirla ?
.
Los comentarios en la fuente abordan la diferencia claramente. Por qué esta información no se presenta a través de comentarios de documentación XML es un misterio para mí.
EscapeUriString:
Este método escapará a cualquier carácter que no sea un carácter reservado o no reservado, incluidos los signos de porcentaje. Tenga en cuenta que EscapeUriString tampoco escapará a un signo '#'.
EscapeDataString:
Este método escapará a cualquier carácter que no sea un carácter no reservado, incluidos los signos de porcentaje.
Entonces, la diferencia está en cómo manejan los caracteres reservados . EscapeDataString
se les escapa; EscapeUriString
no.
Según la RFC , los caracteres reservados son::/?#[]@!$&'()*+,;=
Para completar, los caracteres no reservados son alfanuméricos y -._~
Ambos métodos escapan caracteres que no están reservados ni no reservados.
No estoy de acuerdo con la noción general de que EscapeUriString
es malo. Creo que un método que escapa solo de caracteres ilegales (como espacios) y no caracteres reservados es útil. Pero tiene una peculiaridad en cómo maneja al %
personaje. Los caracteres codificados en porcentaje ( %
seguidos de 2 dígitos hexadecimales) son legales en un URI. Creo que EscapeUriString
sería mucho más útil si detectara este patrón y evitara la codificación %
cuando proceda inmediatamente con 2 dígitos hexadecimales.
Un simple ejemplo
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
*/
Uri.EscapeDataString()
, como se explica en la respuesta de @ Livven. Con otros enfoques, el sistema simplemente no tiene suficiente información para producir el resultado previsto para cada entrada posible.