Server.UrlEncode vs.HttpUtility.UrlEncode

Respuestas:

133

HttpServerUtility.UrlEncodeutilizará HttpUtility.UrlEncodeinternamente No hay diferencia específica. La razón de la existencia de Server.UrlEncodees la compatibilidad con ASP clásico.

Mehrdad Afshari
fuente
3
En cuanto a lo que se escapa. Internamente llama a esta función referencesource.microsoft.com/#System/net/System/Net/…
Jeff
Para los lectores: mire la respuesta de Joel Muller a continuación. Esa es la forma más efectiva de codificar URL: stackoverflow.com/a/603962/190476
Sudhanshu Mishra
264

Tuve dolores de cabeza significativos con estos métodos antes, le recomiendo que evite cualquier variante UrlEncodey, en su lugar, useUri.EscapeDataString , al menos ese tiene un comportamiento comprensible.

Veamos...

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

Pero mi favorito personal tiene que ser HttpUtility.UrlPathEncode ; esto es realmente incomprensible. Codifica:

  • "" ==> "% 20"
  • "100% true" ==> "100 %% 20true" (ok, tu url está rota ahora)
  • "prueba A.aspx # anclaje B" ==> "prueba% 20A.aspx # anclaje% 20B "
  • "test A.aspx? hmm # anchor B" ==> "test% 20A.aspx? hmm #anchor B " (¡ observe la diferencia con la secuencia de escape anterior! )

También tiene la documentación de MSDN maravillosamente específica "Codifica la porción de ruta de una cadena URL para una transmisión HTTP confiable desde el servidor web a un cliente". - Sin explicar realmente lo que hace. Es menos probable que te dispares en el pie con un Uzi ...

En resumen, quédese con Uri.EscapeDataString .

Eamon Nerbonne
fuente
44
Y desafortunadamente eso todavía no funciona cuando se realizan solicitudes HTTP en algunos servidores web: Uri.EscapeDataString () no codifica "!" o "'", que difiere de cómo funcionan la mayoría de las implementaciones de escape () del navegador ...
Chris R. Donnelly
66
! y 'no se supone que los caracteres estén codificados; pero si un servidor web con errores requiere esto, es fácil de solucionar. Evite la función de escape de javascript: es intrínsecamente defectuoso (imposible de ida y vuelta, por ejemplo). Ver xkr.us/articles/javascript/encode-compare , pero en resumen; puede usar encodeUriComponent () en su lugar, que se comporta de manera similar a EscapeDataString: ¡codifica de manera predecible y reversible una cadena, y tampoco codifica! y 'personajes.
Eamon Nerbonne
2
Esto es antiguo, pero la pregunta llegó a la primera página, así que ... La parte de ruta de una cadena de URL es la parte entre el dominio y el? o # en una url.
Powerlord
2
@Tim: puede haber varios ?y quién puede decir cuáles se codificarán y cuáles servirán como separadores. En cuanto al espacio: en ambos casos, el espacio está en el hash, por lo que la presencia o ausencia de un fragmento de consulta no debería importar. Y finalmente, es imperdonable corromper un Uri como en el segundo ejemplo que contiene un%. El UrlPathEncodemétodo es simple y nunca debe usarse.
Eamon Nerbonne
1
Creo que mi respuesta en stackoverflow.com/a/13993486/237091 puede arrojar algo de luz sobre el uso previsto de UrlEncode / UrlPathEncode.
Scott Stafford
60

Avance rápido casi 9 años desde que esto se solicitó por primera vez, y en el mundo de .NET Core y .NET Standard, parece que las opciones más comunes que tenemos para la codificación de URL son WebUtility.UrlEncode (bajo System.Net) y Uri.EscapeDataString . A juzgar por la respuesta más popular aquí y en otros lugares, Uri.EscapeDataString parece ser preferible. ¿Pero es? Hice un análisis para comprender las diferencias y esto es lo que se me ocurrió:

Para propósitos de codificación de URL, los caracteres encajan en una de 3 categorías: sin reserva (legal en una URL); reservado (legal en pero tiene un significado especial, por lo que es posible que desee codificarlo); y todo lo demás (siempre debe estar codificado).

Según la RFC , los caracteres reservados son::/?#[]@!$&'()*+,;=

Y los caracteres no reservados son alfanuméricos y -._~

El veredicto

Uri.EscapeDataString define claramente su misión:% -encode todos los caracteres reservados e ilegales. WebUtility.UrlEncode es más ambiguo tanto en definición como en implementación. Curiosamente, codifica algunos caracteres reservados pero no otros (¿por qué paréntesis y no paréntesis?), Y aún más extraño codifica ese carácter inocentemente sin reservas ~.

Por lo tanto, estoy de acuerdo con el consejo popular: use Uri.EscapeDataString cuando sea posible y entienda que los caracteres reservados como /y ?serán codificados. Si necesita lidiar con cadenas potencialmente grandes, particularmente con contenido de formulario codificado con URL, deberá recurrir a WebUtility.UrlEncode y aceptar sus peculiaridades, o de lo contrario solucionar el problema.


EDIT: He intentado rectificar TODOS los caprichos mencionados anteriormente en Flurl a través de las Url.Encode, Url.EncodeIllegalCharactersy Url.Decodelos métodos estáticos. Estos están en el paquete principal (que es pequeño y no incluye todas las cosas de HTTP), o siéntase libre de extraerlos de la fuente. Agradezco cualquier comentario / comentario que tenga sobre estos.


Aquí está el código que usé para descubrir qué caracteres están codificados de manera 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
fuente
2
¡Esto es brillante!
Jorge Aguirre
1
Gran trabajo para verificar la solución sugerida en el marco moderno .net.
Neowizard
Cabe mencionar que existen algunas diferencias entre WebUtility y HttpUtility . WebUtility usa mayúsculas y HttpUtility usa minúsculas para entidades hexa. Además, HttpUtility no se incluyó en versiones antiguas de subconjuntos de .NET Framework "Client Profile". WebUtility está disponible desde .NET Framework 4.0.
tibx
28

Tenga en cuenta que probablemente no debería usar ninguno de esos métodos. Biblioteca de secuencias de comandos contra sitios cruzados de Microsoft incluye reemplazos HttpUtility.UrlEncodey HttpUtility.HtmlEncodeque cumplen con los estándares y son más seguros. Como beneficio adicional, también obtienes un JavaScriptEncodemétodo.

Joel Mueller
fuente
Después de leer la documentación y las preguntas frecuentes en el enlace proporcionado, ¡creo que esta respuesta es la mejor y más segura forma de codificar datos! ¡Muchas gracias por compartir esto!
Sudhanshu Mishra
El enlace ya no funciona. ¿Cuáles son los métodos de reemplazo?
Edward Brey
@EdwardBrey Esta es la última versión de la biblioteca de secuencias de comandos del sitio de Anti-Cross: microsoft.com/en-au/download/details.aspx?id=28589
Sudhanshu Mishra
11

Server.UrlEncode () está ahí para proporcionar compatibilidad con versiones anteriores de ASP clásico,

Server.UrlEncode(str);

Es equivalente a:

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

Lo mismo, Server.UrlEncode()llamadasHttpUtility.UrlEncode()

andleer
fuente