with querystring query parametros parameter obtener net from aspx asp c# .net url query-string

parametros - request.querystring c#



¿Cómo construir una cadena de consulta para una URL en C#? (30)

Una tarea común cuando se invocan recursos web desde un código es crear una cadena de consulta para incluir todos los parámetros necesarios. Si bien, por supuesto, no hay ciencia espacial, hay algunos detalles ingeniosos de los que debe ocuparse, agregar un & si no el 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 uno esperaría 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 manera más elegante y limpia de hacer lo anterior?


¿Qué tal crear métodos de extensión que le permitan agregar los parámetros en un estilo fluido como este?

string a = "http://www.somedomain.com/somepage.html" .AddQueryParam("A", "TheValueOfA") .AddQueryParam("B", "TheValueOfB") .AddQueryParam("Z", "TheValueOfZ"); string b = new StringBuilder("http://www.somedomain.com/anotherpage.html") .AddQueryParam("A", "TheValueOfA") .AddQueryParam("B", "TheValueOfB") .AddQueryParam("Z", "TheValueOfZ") .ToString();

Aquí está la sobrecarga que utiliza una string :

public static string AddQueryParam( this string source, string key, string value) { string delim; if ((source == null) || !source.Contains("?")) { delim = "?"; } else if (source.EndsWith("?") || source.EndsWith("&")) { delim = string.Empty; } else { delim = "&"; } return source + delim + HttpUtility.UrlEncode(key) + "=" + HttpUtility.UrlEncode(value); }

Y aquí está la sobrecarga que utiliza un StringBuilder :

public static StringBuilder AddQueryParam( this StringBuilder source, string key, string value) { bool hasQuery = false; for (int i = 0; i < source.Length; i++) { if (source[i] == ''?'') { hasQuery = true; break; } } string delim; if (!hasQuery) { delim = "?"; } else if ((source[source.Length - 1] == ''?'') || (source[source.Length - 1] == ''&'')) { delim = string.Empty; } else { delim = "&"; } return source.Append(delim).Append(HttpUtility.UrlEncode(key)) .Append("=").Append(HttpUtility.UrlEncode(value)); }


Añade esta clase a tu proyecto

using System; using System.Collections.Generic; using System.Linq; using System.Web; public class QueryStringBuilder { private readonly List<KeyValuePair<string, object>> _list; public QueryStringBuilder() { _list = new List<KeyValuePair<string, object>>(); } public void Add(string name, object value) { _list.Add(new KeyValuePair<string, object>(name, value)); } public override string ToString() { return String.Join("&", _list.Select(kvp => String.Concat(Uri.EscapeDataString(kvp.Key), "=", Uri.EscapeDataString(kvp.Value.ToString())))); } }

Y úsalo así:

var actual = new QueryStringBuilder { {"foo", 123}, {"bar", "val31"}, {"bar", "val32"} }; actual.Add("a+b", "c+d"); actual.ToString(); // "foo=123&bar=val31&bar=val32&a%2bb=c%2bd"


Agregué el siguiente método a mi clase de PageBase.

protected void Redirect(string url) { Response.Redirect(url); } protected void Redirect(string url, NameValueCollection querystrings) { StringBuilder redirectUrl = new StringBuilder(url); if (querystrings != null) { for (int index = 0; index < querystrings.Count; index++) { if (index == 0) { redirectUrl.Append("?"); } redirectUrl.Append(querystrings.Keys[index]); redirectUrl.Append("="); redirectUrl.Append(HttpUtility.UrlEncode(querystrings[index])); if (index < querystrings.Count - 1) { redirectUrl.Append("&"); } } } this.Redirect(redirectUrl.ToString()); }

Llamar:

NameValueCollection querystrings = new NameValueCollection(); querystrings.Add("language", "en"); querystrings.Add("id", "134"); this.Redirect("http://www.mypage.com", querystrings);


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 parece 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 oculte ineficiencias.

  • Maneja múltiples valores por clave. (No lo necesitaba yo solo, solo para silenciar a Mauricio;)

    public string ToQueryString(NameValueCollection nvc) { StringBuilder sb = new StringBuilder("?"); bool first = true; foreach (string key in nvc.AllKeys) { foreach (string value in nvc.GetValues(key)) { if (!first) { sb.Append("&"); } sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value)); first = false; } } return sb.ToString(); }

Ejemplo de uso

var queryParams = new NameValueCollection() { { "x", "1" }, { "y", "2" }, { "foo", "bar" }, { "foo", "baz" }, { "special chars", "? = &" }, }; string url = "http://example.com/stuff" + ToQueryString(queryParams); Console.WriteLine(url);

Salida

http://example.com/stuff?x=1&y=2&foo=bar&foo=baz&special%20chars=%3F%20%3D%20%26


Combinó las mejores respuestas para crear una versión anónima del objeto :

var queryString = HttpUtility2.BuildQueryString(new { key2 = "value2", key1 = "value1", });

Eso genera esto:

key2 = value2 & key1 = value1

Aquí está el código:

public static class HttpUtility2 { public static string BuildQueryString<T>(T obj) { var queryString = HttpUtility.ParseQueryString(string.Empty); foreach (var property in TypeDescriptor.GetProperties(typeof(T)).Cast<PropertyDescriptor>()) { var value = (property.GetValue(obj) ?? "").ToString(); queryString.Add(property.Name, value); } return queryString.ToString(); } }


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:

using System.Web; public static class HttpExtensions { public static Uri AddQuery(this Uri uri, string name, string value) { var httpValueCollection = HttpUtility.ParseQueryString(uri.Query); httpValueCollection.Remove(name); httpValueCollection.Add(name, value); var ub = new UriBuilder(uri); ub.Query = httpValueCollection.ToString(); return ub.Uri; } }

Uso:

Uri url = new Uri("http://localhost/rest/something/browse"). AddQuery("page", "0"). AddQuery("pageSize", "200");

Edición - Variante que cumple con los estándares

Como señalaron varias personas, httpValueCollection.ToString() codifica los caracteres Unicode de una manera que non-standards-compliant . Esta es una variante del mismo método de extensión que maneja dichos caracteres invocando el método HttpUtility.UrlEncode lugar del método obsoleto HttpUtility.UrlEncodeUnicode .

using System.Web; public static Uri AddQuery(this Uri uri, string name, string value) { var httpValueCollection = HttpUtility.ParseQueryString(uri.Query); httpValueCollection.Remove(name); httpValueCollection.Add(name, value); var ub = new UriBuilder(uri); // this code block is taken from httpValueCollection.ToString() method // and modified so it encodes strings with HttpUtility.UrlEncode if (httpValueCollection.Count == 0) ub.Query = String.Empty; else { var sb = new StringBuilder(); for (int i = 0; i < httpValueCollection.Count; i++) { string text = httpValueCollection.GetKey(i); { text = HttpUtility.UrlEncode(text); string val = (text != null) ? (text + "=") : string.Empty; string[] vals = httpValueCollection.GetValues(i); if (sb.Length > 0) sb.Append(''&''); if (vals == null || vals.Length == 0) sb.Append(val); else { if (vals.Length == 1) { sb.Append(val); sb.Append(HttpUtility.UrlEncode(vals[0])); } else { for (int j = 0; j < vals.Length; j++) { if (j > 0) sb.Append(''&''); sb.Append(val); sb.Append(HttpUtility.UrlEncode(vals[j])); } } } } } ub.Query = sb.ToString(); } return ub.Uri; }


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,

var res = Request.QueryString.Duplicate() .ChangeField("field1", "somevalue") .ChangeField("field2", "only if following is true", true) .ChangeField("id", id, id>0) .WriteLocalPathWithQuery(Request.Url)); //Uses context to write the path

Para más 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.


Esta es 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 es extensiones sobre envoltorios para la capacidad de descubrimiento por otros miembros del equipo para cosas como esta. Tenga en cuenta que existe controversia acerca de los métodos de codificación, muchas publicaciones al respecto en (una de esas post ) y los bloggers de MSDN (como esta ).

public static string ToQueryString(this NameValueCollection source) { return String.Join("&", source.AllKeys .SelectMany(key => source.GetValues(key) .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)))) .ToArray()); }

Edición: con soporte nulo, aunque probablemente deba adaptarlo a su situación particular

public static string ToQueryString(this NameValueCollection source, bool removeEmptyEntries) { return source != null ? String.Join("&", source.AllKeys .Where(key => !removeEmptyEntries || source.GetValues(key) .Where(value => !String.IsNullOrEmpty(value)) .Any()) .SelectMany(key => source.GetValues(key) .Where(value => !removeEmptyEntries || !String.IsNullOrEmpty(value)) .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), value != null ? HttpUtility.UrlEncode(value) : string.Empty))) .ToArray()) : string.Empty; }


Igual que la solución aceptada, pero transferida a la sintaxis LINQ del "punto" ...

private string ToQueryString(NameValueCollection nvc) { if (nvc == null) return String.Empty; var queryParams = string.Join("&", nvc.AllKeys.Select(key => string.Join("&", nvc.GetValues(key).Select(v => string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(v)))))); return "?" + queryParams; }


Mi oferta:

public static Uri AddQuery(this Uri uri, string name, string value) { // this actually returns HttpValueCollection : NameValueCollection // which uses unicode compliant encoding on ToString() var query = HttpUtility.ParseQueryString(uri.Query); query.Add(name, value); var uriBuilder = new UriBuilder(uri) { Query = query.ToString() }; return uriBuilder.Uri; }

Uso:

var uri = new Uri("http://.com").AddQuery("such", "method") .AddQuery("wow", "soFluent"); // http://.com?such=method&wow=soFluent


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, por lo que no puedo usar ParseQueryString.

En su lugar, utilicé System.Net.Http.FormUrlEncodedContent así:

var url = new UriBuilder("http://example.com"); url.Query = new FormUrlEncodedContent(new Dictionary<string,string>() { {"param1", "val1"}, {"param2", "val2"}, {"param3", "val3"}, }).ReadAsStringAsync().Result;


Puede crear una nueva instancia grabable de HttpValueCollection llamando a System.Web.HttpUtility.ParseQueryString(string.Empty) , y luego usarlo como cualquier NameValueCollection . Una vez que haya agregado los valores que desea, puede llamar a ToString en la colección para obtener una cadena de consulta, de la siguiente manera:

NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty); queryString["key1"] = "value1"; queryString["key2"] = "value2"; return queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded

La HttpValueCollection es interna y, por lo tanto, no puede construir una instancia directamente. Sin embargo, una vez que obtenga una instancia, puede usarla como cualquier otra NameValueCollection . Dado que el objeto real con el que está trabajando es HttpValueCollection , el método ToString que se invoca llamará al método anulado en HttpValueCollection , 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 clase Microsoft.AspNetCore.WebUtilities.QueryHelpers , que simplifica esto enormemente.

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers


Respondí una pregunta similar hace un tiempo. Básicamente, la mejor manera sería usar la clase HttpValueCollection , que en realidad es la propiedad Request.QueryString de ASP.NET, desafortunadamente es interna en el marco .NET. Puedes usar Reflector para agarrarlo (y colocarlo en tu clase de Utils). De esta manera usted podría manipular la cadena de consulta como un NameValueCollection, pero con todos los problemas de codificación / decodificación de url resueltos para usted.

HttpValueCollection extiende NameValueCollection y tiene un constructor que toma una cadena de consulta codificada (se incluyen los signos y signos de interrogación), y reemplaza un método ToString() para luego reconstruir la cadena de consulta de la colección subyacente.

Ejemplo:

var coll = new HttpValueCollection(); coll["userId"] = "50"; coll["paramA"] = "A"; coll["paramB"] = "B"; string query = coll.ToString(true); // true means use urlencode Console.WriteLine(query); // prints: userId=50&paramA=A&paramB=B


Si mira debajo del capó, la propiedad QueryString es NameValueCollection. Cuando he hecho cosas similares, por lo general me ha interesado la serialización y la deserialización, por lo que mi sugerencia es crear una colección NameValue y luego pasar a:

using System.Web; using System.Collections.Specialized; private string ToQueryString(NameValueCollection nvc) { var array = (from key in nvc.AllKeys from value in nvc.GetValues(key) select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))) .ToArray(); return "?" + string.Join("&", array); }

Posiblemente podría haberlo formateado mejor :)

Me imagino que también hay una forma súper elegante de hacer esto en LINQ ...


Sin probar, pero creo que algo en este sentido funcionaría bastante bien

public class QueryString { private Dictionary<string,string> _Params = new Dictionary<string,string>(); public overide ToString() { List<string> returnParams = new List<string>(); foreach (KeyValuePair param in _Params) { returnParams.Add(String.Format("{0}={1}", param.Key, param.Value)); } // return String.Format("?{0}", String.Join("&", returnParams.ToArray())); // credit annakata return "?" + String.Join("&", returnParams.ToArray()); } public void Add(string key, string value) { _Params.Add(key, HttpUtility.UrlEncode(value)); } } QueryString query = new QueryString(); query.Add("param1", "value1"); query.Add("param2", "value2"); return query.ToString();


Solo quería tirar en mis 2 centavos:

public static class HttpClientExt { public static Uri AddQueryParams(this Uri uri, string query) { var ub = new UriBuilder(uri); ub.Query = string.IsNullOrEmpty(uri.Query) ? query : string.Join("&", uri.Query.Substring(1), query); return ub.Uri; } public static Uri AddQueryParams(this Uri uri, IEnumerable<string> query) { return uri.AddQueryParams(string.Join("&", query)); } public static Uri AddQueryParams(this Uri uri, string key, string value) { return uri.AddQueryParams(string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))); } public static Uri AddQueryParams(this Uri uri, params KeyValuePair<string,string>[] kvps) { return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value)))); } public static Uri AddQueryParams(this Uri uri, IDictionary<string, string> kvps) { return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value)))); } public static Uri AddQueryParams(this Uri uri, NameValueCollection nvc) { return uri.AddQueryParams(nvc.AllKeys.SelectMany(nvc.GetValues, (key, value) => string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)))); } }

Los documentos dicen que uri.Querycomenzará con un ?si no está vacío y usted debería recortarlo si lo va a modificar.

Tenga en cuenta que HttpUtility.UrlEncodese encuentra en System.Web.

Uso:

var uri = new Uri("https://api.del.icio.us/v1/posts/suggest").AddQueryParam("url","http://.com")


Suponiendo que desea reducir las dependencias a otros ensamblajes y mantener las cosas simples, puede hacer:

var sb = new System.Text.StringBuilder(); sb.Append("a=" + HttpUtility.UrlEncode("TheValueOfA") + "&"); sb.Append("b=" + HttpUtility.UrlEncode("TheValueOfB") + "&"); sb.Append("c=" + HttpUtility.UrlEncode("TheValueOfC") + "&"); sb.Append("d=" + HttpUtility.UrlEncode("TheValueOfD") + "&"); sb.Remove(sb.Length-1, 1); // Remove the final ''&'' string result = sb.ToString();

Esto funciona bien con los bucles también. La eliminación final de ampersand debe ir fuera del bucle.

Tenga en cuenta que el operador de concatenación se utiliza para mejorar la legibilidad. El costo de usarlo comparado con el costo de usar un StringBuilder es mínimo (creo que Jeff Atwood publicó algo sobre este tema).


Tengo un método de extensión para Uri que:

  • Acepta objetos anónimos: uri.WithQuery(new { name = "value" })
  • Acepta colecciones de pares de string/string (por ejemplo, Dictionary`2 ).
  • Acepta colecciones de pares de string/object (por ejemplo, RouteValueDictionary ).
  • Acepta NameValueCollection s.
  • Ordena los valores de consulta por clave para que los mismos valores produzcan URI iguales.
  • Admite múltiples valores por clave, conservando su orden original.

La versión documentada se puede encontrar here .

La extensión:

public static Uri WithQuery(this Uri uri, object values) { if (uri == null) throw new ArgumentNullException(nameof(uri)); if (values != null) { var query = string.Join( "&", from p in ParseQueryValues(values) where !string.IsNullOrWhiteSpace(p.Key) let k = HttpUtility.UrlEncode(p.Key.Trim()) let v = HttpUtility.UrlEncode(p.Value) orderby k select string.IsNullOrEmpty(v) ? k : $"{k}={v}"); if (query.Length != 0 || uri.Query.Length != 0) uri = new UriBuilder(uri) { Query = query }.Uri; } return uri; }

El analizador de consultas:

private static IEnumerable<KeyValuePair<string, string>> ParseQueryValues(object values) { // Check if a name/value collection. var nvc = values as NameValueCollection; if (nvc != null) return from key in nvc.AllKeys from val in nvc.GetValues(key) select new KeyValuePair<string, string>(key, val); // Check if a string/string dictionary. var ssd = values as IEnumerable<KeyValuePair<string, string>>; if (ssd != null) return ssd; // Check if a string/object dictionary. var sod = values as IEnumerable<KeyValuePair<string, object>>; if (sod == null) { // Check if a non-generic dictionary. var ngd = values as IDictionary; if (ngd != null) sod = ngd.Cast<dynamic>().ToDictionary<dynamic, string, object>( p => p.Key.ToString(), p => p.Value as object); // Convert object properties to dictionary. if (sod == null) sod = new RouteValueDictionary(values); } // Normalize and return the values. return from pair in sod from val in pair.Value as IEnumerable<string> ?? new[] { pair.Value?.ToString() } select new KeyValuePair<string, string>(pair.Key, val); }

Aquí están las pruebas:

var uri = new Uri("https://.com/yo?oldKey=oldValue"); // Test with a string/string dictionary. var q = uri.WithQuery(new Dictionary<string, string> { ["k1"] = string.Empty, ["k2"] = null, ["k3"] = "v3" }); Debug.Assert(q == new Uri( "https://.com/yo?k1&k2&k3=v3")); // Test with a string/object dictionary. q = uri.WithQuery(new Dictionary<string, object> { ["k1"] = "v1", ["k2"] = new[] { "v2a", "v2b" }, ["k3"] = null }); Debug.Assert(q == new Uri( "https://.com/yo?k1=v1&k2=v2a&k2=v2b&k3")); // Test with a name/value collection. var nvc = new NameValueCollection() { ["k1"] = string.Empty, ["k2"] = "v2a" }; nvc.Add("k2", "v2b"); q = uri.WithQuery(nvc); Debug.Assert(q == new Uri( "https://.com/yo?k1&k2=v2a&k2=v2b")); // Test with any dictionary. q = uri.WithQuery(new Dictionary<int, HashSet<string>> { [1] = new HashSet<string> { "v1" }, [2] = new HashSet<string> { "v2a", "v2b" }, [3] = null }); Debug.Assert(q == new Uri( "https://.com/yo?1=v1&2=v2a&2=v2b&3")); // Test with an anonymous object. q = uri.WithQuery(new { k1 = "v1", k2 = new[] { "v2a", "v2b" }, k3 = new List<string> { "v3" }, k4 = true, k5 = null as Queue<string> }); Debug.Assert(q == new Uri( "https://.com/yo?k1=v1&k2=v2a&k2=v2b&k3=v3&k4=True&k5")); // Keep existing query using a name/value collection. nvc = HttpUtility.ParseQueryString(uri.Query); nvc.Add("newKey", "newValue"); q = uri.WithQuery(nvc); Debug.Assert(q == new Uri( "https://.com/yo?newKey=newValue&oldKey=oldValue")); // Merge two query objects using the RouteValueDictionary. var an1 = new { k1 = "v1" }; var an2 = new { k2 = "v2" }; q = uri.WithQuery( new RouteValueDictionary(an1).Concat( new RouteValueDictionary(an2))); Debug.Assert(q == new Uri( "https://.com/yo?k1=v1&k2=v2"));


Una versión basada en el método de extensión rápida:

class Program { static void Main(string[] args) { var parameters = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("A", "AValue"), new KeyValuePair<string, string>("B", "BValue") }; string output = "?" + string.Join("&", parameters.ConvertAll(param => param.ToQueryString()).ToArray()); } } public static class KeyValueExtensions { public static string ToQueryString(this KeyValuePair<string, string> obj) { return obj.Key + "=" + HttpUtility.UrlEncode(obj.Value); } }

Podría usar una cláusula where para seleccionar qué parámetros se agregarán a la cadena.


[También entrada tardía]

Clase de envoltura capaz de encadenar para HttpValueCollection:

namespace System.Web.Mvc { public class QueryStringBuilder { private NameValueCollection collection; public QueryStringBuilder() { collection = System.Web.HttpUtility.ParseQueryString(string.Empty); } public QueryStringBuilder Add(string key, string value) { collection.Add(key, value); return this; } public QueryStringBuilder Remove(string key) { collection.Remove(key); return this; } public string this[string key] { get { return collection[key]; } set { collection[key] = value; } } public string ToString() { return collection.ToString(); } } }

Ejemplo de uso:

QueryStringBuilder parameters = new QueryStringBuilder() .Add("view", ViewBag.PageView) .Add("page", ViewBag.PageNumber) .Add("size", ViewBag.PageSize); string queryString = parameters.ToString();


Flurl [divulgación: soy el autor] admite la creación de cadenas de consulta a través de objetos anónimos (entre otras formas):

var url = "http://www.some-api.com".SetQueryParams(new { api_key = ConfigurationManager.AppSettings["SomeApiKey"], max_results = 20, q = "Don''t worry, I''ll get encoded!" });

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:

T result = await "https://api.mysite.com" .AppendPathSegment("person") .SetQueryParams(new { ap_key = "my-key" }) .WithOAuthBearerToken("MyToken") .PostJsonAsync(new { first_name = firstName, last_name = lastName }) .ReceiveJson<T>();

El paquete completo está disponible en NuGet:

PM> Install-Package Flurl.Http

o simplemente el creador de URL independiente:

PM> Install-Package Flurl


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 manipular el objeto QueryString de la solicitud actual.

@helper GetQueryStringWithValue(string key, string value) { var queryString = System.Web.HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString()); queryString[key] = value; @Html.Raw(queryString.ToString()) }

Lo uso así:

location.search = ''[email protected]("var-name", "var-value")'';

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.


Esta es idéntica a la respuesta aceptada, excepto un poco más compacta:

private string ToQueryString(NameValueCollection nvc) { return "?" + string.Join("&", nvc.AllKeys.Select(k => string.Format("{0}={1}", HttpUtility.UrlEncode(k), HttpUtility.UrlEncode(nvc[k])))); }


Funciona para múltiples valores por clave en NameValueCollection.

ej: { {"k1", "v1"}, {"k1", "v1"} }=>?k1=v1&k1=v1

/// <summary> /// Get query string for name value collection. /// </summary> public static string ToQueryString(this NameValueCollection collection, bool prefixQuestionMark = true) { collection.NullArgumentCheck(); if (collection.Keys.Count == 0) { return ""; } var buffer = new StringBuilder(); if (prefixQuestionMark) { buffer.Append("?"); } var append = false; for (int i = 0; i < collection.Keys.Count; i++) { var key = collection.Keys[i]; var values = collection.GetValues(key); key.NullCheck(); values.NullCheck(); foreach (var value in values) { if (append) { buffer.Append("&"); } append = true; buffer.AppendFormat("{0}={1}", key.UrlEncode(), value.UrlEncode()); } } return buffer.ToString(); }


Solo para aquellos que necesitan la versión VB.NET de la mejor respuesta:

Public Function ToQueryString(nvc As System.Collections.Specialized.NameValueCollection) As String Dim array As String() = nvc.AllKeys.SelectMany(Function(key As String) nvc.GetValues(key), Function(key As String, value As String) String.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(key), System.Web.HttpUtility.UrlEncode(value))).ToArray() Return "?" + String.Join("&", array) End Function

Y la versión sin LINQ:

Public Function ToQueryString(nvc As System.Collections.Specialized.NameValueCollection) As String Dim lsParams As New List(Of String)() For Each strKey As String In nvc.AllKeys Dim astrValue As String() = nvc.GetValues(strKey) For Each strValue As String In astrValue lsParams.Add(String.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(strKey), System.Web.HttpUtility.UrlEncode(strValue))) Next '' Next strValue Next '' strKey Dim astrParams As String() = lsParams.ToArray() lsParams.Clear() lsParams = Nothing Return "?" + String.Join("&", astrParams) End Function '' ToQueryString

Y la versión C # sin LINQ:

public static string ToQueryString(System.Collections.Specialized.NameValueCollection nvc) { List<string> lsParams = new List<string>(); foreach (string strKey in nvc.AllKeys) { string[] astrValue = nvc.GetValues(strKey); foreach (string strValue in astrValue) { lsParams.Add(string.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(strKey), System.Web.HttpUtility.UrlEncode(strValue))); } // Next strValue } // Next strKey string[] astrParams =lsParams.ToArray(); lsParams.Clear(); lsParams = null; return "?" + string.Join("&", astrParams); } // End Function ToQueryString


El código a continuación se retira de la HttpValueCollectionimplementación de ToString, a través de ILSpy, que le da una cadena de consulta name = value.

Desafortunadamente, HttpValueCollection es una clase interna que solo recuperas si la usas HttpUtility.ParseQueryString(). Le quité todas las partes de viewstate y se codifica de forma predeterminada:

public static class HttpExtensions { public static string ToQueryString(this NameValueCollection collection) { // This is based off the NameValueCollection.ToString() implementation int count = collection.Count; if (count == 0) return string.Empty; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < count; i++) { string text = collection.GetKey(i); text = HttpUtility.UrlEncodeUnicode(text); string value = (text != null) ? (text + "=") : string.Empty; string[] values = collection.GetValues(i); if (stringBuilder.Length > 0) { stringBuilder.Append(''&''); } if (values == null || values.Length == 0) { stringBuilder.Append(value); } else { if (values.Length == 1) { stringBuilder.Append(value); string text2 = values[0]; text2 = HttpUtility.UrlEncodeUnicode(text2); stringBuilder.Append(text2); } else { for (int j = 0; j < values.Length; j++) { if (j > 0) { stringBuilder.Append(''&''); } stringBuilder.Append(value); string text2 = values[j]; text2 = HttpUtility.UrlEncodeUnicode(text2); stringBuilder.Append(text2); } } } } return stringBuilder.ToString(); } }


Esta es otra forma ( tal vez redundante: -] de hacer eso.

Los conceptos conceptuales son los mismos de la respuesta de en esta página (consulte here ).

Pero esta clase es más eficiente, ya que itera a través de todas las claves solo una vez: cuando ToStringse invoca.

El código de formato también está semplificado y mejorado.

Espero que pueda ser de ayuda.

public sealed class QueryStringBuilder { public QueryStringBuilder() { this.inner = HttpUtility.ParseQueryString(string.Empty); } public QueryStringBuilder(string queryString) { this.inner = HttpUtility.ParseQueryString(queryString); } public QueryStringBuilder(string queryString, Encoding encoding) { this.inner = HttpUtility.ParseQueryString(queryString, encoding); } private readonly NameValueCollection inner; public QueryStringBuilder AddKey(string key, string value) { this.inner.Add(key, value); return this; } public QueryStringBuilder RemoveKey(string key) { this.inner.Remove(key); return this; } public QueryStringBuilder Clear() { this.inner.Clear(); return this; } public override String ToString() { if (this.inner.Count == 0) return string.Empty; var builder = new StringBuilder(); for (int i = 0; i < this.inner.Count; i++) { if (builder.Length > 0) builder.Append(''&''); var key = this.inner.GetKey(i); var values = this.inner.GetValues(i); if (key == null || values == null || values.Length == 0) continue; for (int j = 0; j < values.Length; j++) { if (j > 0) builder.Append(''&''); builder.Append(HttpUtility.UrlEncode(key)); builder.Append(''=''); builder.Append(HttpUtility.UrlEncode(values[j])); } } return builder.ToString(); } }


Fui con la solución propuesta por DSO (contestada 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 el diccionario en lugar de NameValueCollection.

public static Dictionary<string, string> QueryParametersDictionary() { var dictionary = new Dictionary<string, string>(); dictionary.Add("name", "John Doe"); dictionary.Add("address.city", "Seattle"); dictionary.Add("address.state_code", "WA"); dictionary.Add("api_key", "5352345263456345635"); return dictionary; } public static string ToQueryString(Dictionary<string, string> nvc) { StringBuilder sb = new StringBuilder(); bool first = true; foreach (KeyValuePair<string, string> pair in nvc) { if (!first) { sb.Append("&"); } sb.AppendFormat("{0}={1}", Uri.EscapeDataString(pair.Key), Uri.EscapeDataString(pair.Value)); first = false; } return sb.ToString(); }


public static string ToQueryString(this Dictionary<string, string> source) { return String.Join("&", source.Select(kvp => String.Format("{0}={1}", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))).ToArray()); } public static string ToQueryString(this NameValueCollection source) { return String.Join("&", source.Cast<string>().Select(key => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(source[key]))).ToArray()); }


// USAGE [TestMethod] public void TestUrlBuilder() { Console.WriteLine( new UrlBuilder("http://www.google.com?A=B") .AddPath("SomePathName") .AddPath("AnotherPathName") .SetQuery("SomeQueryKey", "SomeQueryValue") .AlterQuery("A", x => x + "C")); }

Salida:

http://www.google.com/SomePathName/AnotherPathName?A=BC&SomeQueryKey=SomeQueryValue

El código; Todos me pueden agradecer en alguna parte, de alguna manera: D

using System; using System.Collections.Generic; using System.Linq; using System.Web; // By Demetris Leptos namespace TheOperator.Foundation.Web { public class UrlBuilder { public string Scheme { get; set; } public string Host { get; set; } public int? Port { get; set; } public List<string> Paths { get; set; } public SortedDictionary<string, string> QueryPairs { get; set; } public UrlBuilder(string url) { this.Paths = new List<string>(); this.QueryPairs = new SortedDictionary<string, string>(); string path = null; string query = null; Uri relativeUri = null; if (!Uri.TryCreate(url, UriKind.Relative, out relativeUri)) { var uriBuilder = new UriBuilder(url); this.Scheme = uriBuilder.Scheme; this.Host = uriBuilder.Host; this.Port = uriBuilder.Port; path = uriBuilder.Path; query = uriBuilder.Query; } else { var queryIndex = url.IndexOf(''?''); if (queryIndex >= 0) { path = url.Substring(0, queryIndex); query = url.Substring(queryIndex + 1); } else { path = url; } } this.Paths.AddRange(path.Split(new char[] { ''/'' }, StringSplitOptions.RemoveEmptyEntries)); if (query != null) { var queryKeyValuePairs = HttpUtility.ParseQueryString(query); foreach (var queryKey in queryKeyValuePairs.AllKeys) { this.QueryPairs[queryKey] = queryKeyValuePairs[queryKey]; } } } public UrlBuilder AddPath(string value) { this.Paths.Add(value); return this; } public UrlBuilder SetQuery(string key, string value) { this.QueryPairs[key] = value; return this; } public UrlBuilder RemoveQuery(string key) { this.QueryPairs.Remove(key); return this; } public UrlBuilder AlterQuery(string key, Func<string, string> alterMethod, bool removeOnNull = false) { string value; this.QueryPairs.TryGetValue(key, out value); value = alterMethod(value); if (removeOnNull && value == null) { return this.RemoveQuery(key); } else { return this.SetQuery(key, value); } } public override string ToString() { var path = !string.IsNullOrWhiteSpace(this.Host) ? string.Join("/", this.Host, string.Join("/", this.Paths)) : string.Join("/", this.Paths); var query = string.Join("&", this.QueryPairs.Select(x => string.Concat(x.Key, "=", HttpUtility.UrlEncode(x.Value)))); return string.Concat( !string.IsNullOrWhiteSpace(this.Scheme) ? string.Concat(this.Scheme, "://") : null, path, !string.IsNullOrWhiteSpace(query) ? string.Concat("?", query) : null); } } }