Una tarea común cuando se llaman recursos web desde un código es construir una cadena de consulta para incluir todos los parámetros necesarios. Si bien, por supuesto, no hay ciencia de cohetes, hay algunos detalles ingeniosos que debe tener en cuenta, como agregar un &
primer parámetro, codificar los parámetros, etc.
El código para hacerlo es muy simple, pero un poco tedioso:
StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A)
{
SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA"));
}
if (NeedsToAddParameter B)
{
if (SB.Length>0) SB.Append("&");
SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}
Esta es una tarea tan común que cabría esperar que exista una clase de utilidad que la haga más elegante y legible. Al escanear MSDN, no pude encontrar uno, lo que me lleva a la siguiente pregunta:
¿Cuál es la forma limpia más elegante que sabes de hacer lo anterior?
c#
.net
url
query-string
Booz
fuente
fuente
Respuestas:
Si observa debajo del capó, la propiedad QueryString es una NameValueCollection. Cuando he hecho cosas similares, generalmente me ha interesado serializar y deserializar, así que mi sugerencia es crear una NameValueCollection y luego pasar a:
Me imagino que también hay una forma súper elegante de hacer esto en LINQ ...
fuente
application/x-www-form-urlencoded
, y en realidad está definido por HTML, con el fin de enviar datos de formulario como parte de unaGET
solicitud. HTML 5 no prohíbe múltiples valores por clave en este formato, y de hecho requiere que el navegador produzca múltiples valores por clave en caso de que la página (incorrectamente) contenga múltiples campos con el mismoname
atributo. Ver goo.gl/uk1AgPuede crear una nueva instancia de escritura
HttpValueCollection
al llamarSystem.Web.HttpUtility.ParseQueryString(string.Empty)
y luego usarla como cualquieraNameValueCollection
. Una vez que haya agregado los valores que desea, puede llamarToString
a la colección para obtener una cadena de consulta, de la siguiente manera:El
HttpValueCollection
es interno y, por lo tanto, no puede construir directamente una instancia. Sin embargo, una vez que obtenga una instancia, puede usarla como cualquier otraNameValueCollection
. Como el objeto real con el que está trabajando es unHttpValueCollection
, llamar al método ToString llamará al método anulado enHttpValueCollection
, que formatea la colección como una cadena de consulta codificada en URL.Después de buscar en SO y en la web una respuesta a un problema similar, esta es la solución más simple que pude encontrar.
.NET Core
Si está trabajando en .NET Core, puede usar la
Microsoft.AspNetCore.WebUtilities.QueryHelpers
clase, que simplifica esto en gran medida.https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers
Código de muestra:
fuente
public static string ToURLQueryString(this IDictionary dict) { ... }
Add
método Es decir,queryString.Add("type", "1"); queryString.Add("type", "2");
usar elAdd
método es probablemente una mejor manera de hacerlo todo el tiempo en realidad.Con la inspiración del comentario de Roy Tinker, terminé usando un método de extensión simple en la clase Uri que mantiene mi código conciso y limpio:
Uso:
Editar: variante compatible con los estándares
Como señalaron varias personas,
httpValueCollection.ToString()
codifica los caracteres Unicode de una manera que no cumple con los estándares . Esta es una variante del mismo método de extensión que maneja dichos caracteres invocando elHttpUtility.UrlEncode
método en lugar del método en desusoHttpUtility.UrlEncodeUnicode
.fuente
Respondí una pregunta similar hace un tiempo. Básicamente, la mejor manera sería usar la clase
HttpValueCollection
, que ASP.NETRequest.QueryString
realidad es propiedad , desafortunadamente es interna en el marco .NET. Puede usar Reflector para agarrarlo (y colocarlo en su clase de Utils). De esta forma, podría manipular la cadena de consulta como una NameValueCollection, pero con todos los problemas de codificación / decodificación de URL atendidos.HttpValueCollection
se extiendeNameValueCollection
y tiene un constructor que toma una cadena de consulta codificada (símbolos y signos de interrogación incluidos), y anula unToString()
método para luego reconstruir la cadena de consulta de la colección subyacente.Ejemplo:
fuente
httpValueCollection.ToString()
en realidad llamahttpValueCollection.ToString(true)
así quetrue
no se requiere agregar la explicidad.Aquí hay una forma fluida / lambda-ish como método de extensión (combinando conceptos en publicaciones anteriores) que admite múltiples valores para la misma clave. Mi preferencia personal son las extensiones sobre los contenedores para la capacidad de descubrimiento por parte de otros miembros del equipo para cosas como esta. Tenga en cuenta que existe una controversia sobre los métodos de codificación, muchas publicaciones al respecto en Stack Overflow (una de esas publicaciones ) y bloggers de MSDN (como esta ).
editar: con soporte nulo, aunque probablemente deba adaptarlo para su situación particular
fuente
Flurl [divulgación: soy el autor] admite la creación de cadenas de consulta a través de objetos anónimos (entre otras formas):
La biblioteca complementaria Flurl.Http opcional le permite hacer llamadas HTTP directamente desde la misma cadena de llamadas fluida, extendiéndola a un cliente REST completo:
El paquete completo está disponible en NuGet:
PM> Install-Package Flurl.Http
o solo el creador de URL independiente:
PM> Install-Package Flurl
fuente
Aquí está mi entrada tardía. No me gustó ninguno de los otros por varias razones, así que escribí el mío.
Esta versión presenta:
Uso de StringBuilder solamente. No hay llamadas ToArray () u otros métodos de extensión. No se ve tan bonito como algunas de las otras respuestas, pero considero que esta es una función central, por lo que la eficiencia es más importante que tener un código "fluido", de una sola línea, que oculta las ineficiencias.
Maneja múltiples valores por clave. (No lo necesitaba yo solo, pero solo para silenciar a Mauricio;)
Ejemplo de uso
Salida
fuente
¿Qué tal crear métodos de extensión que le permitan agregar los parámetros en un estilo fluido como este?
Aquí está la sobrecarga que usa un
string
:Y aquí está la sobrecarga que usa un
StringBuilder
:fuente
NameValueCollection
,HttpValueCollection
o unaUri
primera. ¡Gracias!Necesitaba resolver el mismo problema para una biblioteca de clases portátil (PCL) en la que estoy trabajando. En este caso, no tengo acceso a System.Web, así que no puedo usar ParseQueryString.
En su lugar, usé
System.Net.Http.FormUrlEncodedContent
así:fuente
fuente
.ToArray()
s.Agrega esta clase a tu proyecto
Y úsalo así:
fuente
Mi oferta:
Uso:
fuente
No probado, pero creo que algo en este sentido funcionaría bastante bien
fuente
Una versión basada en el método de extensión rápida:
Puede usar una cláusula where para seleccionar qué parámetros se agregan a la cadena.
fuente
Suponiendo que desea reducir las dependencias a otros ensamblados y mantener las cosas simples, puede hacer lo siguiente:
Esto funciona bien con bucles también. La eliminación final de ampersand debe salir del ciclo.
Tenga en cuenta que el operador de concatenación se utiliza para mejorar la legibilidad. El costo de usarlo en comparación con el costo de usar un StringBuilder es mínimo (creo que Jeff Atwood publicó algo sobre este tema).
fuente
Combinó las respuestas principales para crear una versión de objeto anónimo :
Eso genera esto:
Aquí está el código:
fuente
Igual que la solución aceptada, pero transferida a la sintaxis LINQ "punto" ...
fuente
Tengo un método de extensión para Uri que:
uri.WithQuery(new { name = "value" })
string/string
pares (por ejemplo, Diccionario`2 ).string/object
pares (por ejemplo, RouteValueDictionary ).La versión documentada se puede encontrar aquí .
La extensión:
El analizador de consultas:
Aquí están las pruebas:
fuente
Clase de contenedor de cadena para HttpValueCollection:
Ejemplo de uso:
fuente
Agregué el siguiente método a mi clase de PageBase.
Llamar:
fuente
Escribí algunos métodos de extensión que he encontrado muy útiles al trabajar con QueryStrings. A menudo quiero comenzar con el QueryString actual y modificarlo antes de usarlo. Algo como,
Para más información y la fuente: http://www.charlesrcook.com/archive/2008/07/23/c-extension-methods-for-asp.net-query-string-operations.aspx
Es básico, pero me gusta el estilo.
fuente
Solo quería tirar mis 2 centavos:
Los documentos dicen que
uri.Query
comenzará con un?
si no está vacío y debe recortarlo si va a modificarlo.Tenga en cuenta que
HttpUtility.UrlEncode
se encuentra enSystem.Web
.Uso:
fuente
Si bien no es elegante, opté por una versión más simple que no usa
NameValueCollecitons
, solo un patrón de construcción envueltoStringBuilder
.Según las respuestas existentes, me aseguré de usar
HttpUtility.UrlEncode
llamadas. Se usa así:fuente
Salida:
El código; todos ustedes pueden agradecerme en alguna parte, de alguna manera: D
fuente
Fui con la solución propuesta por DSO (respondida el 2 de agosto de 11 a las 7:29), su solución no requiere el uso de HttpUtility. Sin embargo, según un artículo publicado en Dotnetpearls , usar un Diccionario es más rápido (en rendimiento) que usar NameValueCollection. Aquí está la solución de DSO modificada para usar Dictionary en lugar de NameValueCollection.
fuente
La cadena de consulta se puede agregar a una URL mediante:
https://blog.codingnovice.com/blog
fuente
Escribí un ayudante para mi proyecto de maquinilla de afeitar utilizando algunas de las sugerencias de otras respuestas.
El negocio ParseQueryString es necesario porque no se nos permite alterar el objeto QueryString de la solicitud actual.
Lo uso así:
Si desea que tome más de un valor, simplemente cambie los parámetros a un Diccionario y agregue los pares a la cadena de consulta.
fuente
El siguiente código se elimina de la
HttpValueCollection
implementación deToString
, a través de ILSpy, que le da una cadena de consulta de nombre = valor.Lamentablemente, HttpValueCollection es una clase interna que solo volverá a obtener si la usa
HttpUtility.ParseQueryString()
. Eliminé todas las partes del estado de vista y codifica de manera predeterminada:fuente
Esta es la respuesta idéntica a la aceptada, excepto un poco más compacta:
fuente
Solo para aquellos que necesitan la versión VB.NET de la respuesta superior:
Y la versión sin LINQ:
Y la versión C # sin LINQ:
fuente