asp.net - route - select asp-for asp-items
Cambiar el valor de la cadena de consulta de URL Ășnica (5)
Tengo una página ASP.NET que toma una serie de parámetros en la cadena de consulta:
search.aspx?q=123&source=WebSearch
Esto mostraría la primera página de resultados de búsqueda. Ahora, dentro de la representación de esa página, quiero mostrar un conjunto de enlaces que permiten al usuario saltar a diferentes páginas dentro de los resultados de búsqueda. Puedo hacer esto simplemente agregando &page=1
o &page=2
etc.
Donde se complica es que quiero preservar la cadena de consulta de entrada de la página original para cada parámetro, excepto el que estoy tratando de cambiar. Puede haber otros parámetros en la URL utilizada por otros componentes y el valor que estoy tratando de reemplazar puede o no estar ya definido:
search.aspx?q=123&source=WebSearch&page=1&Theme=Blue
En este caso, para generar un enlace a la siguiente página de resultados, deseo cambiar page=1
a page=2
mientras no se modifica el resto de la cadena de consulta.
¿Hay una forma integrada de hacer esto, o tengo que hacer todo el análisis / recombinación de cadenas manualmente?
Esto es bastante arbitrario, al menos en .NET Core. Y todo se reduce a asp-all-route-data
Considere el siguiente ejemplo trivial (tomado del modelo de vista "paginador" que uso en prácticamente todos los proyectos):
public class SomeViewModel
{
public Dictionary<string, string> NextPageLink(IQueryCollection query)
{
/*
* NOTE: how you derive the "2" is fully up to you
*/
return ParseQueryCollection(query, "page", "2");
}
Dictionary<string, string> ParseQueryCollection(IQueryCollection query, string replacementKey, string replacementValue)
{
var dict = new Dictionary<string, string>()
{
{ replacementKey, replacementValue }
};
foreach (var q in query)
{
if (!string.Equals(q.Key, replacementKey, StringComparison.OrdinalIgnoreCase))
{
dict.Add(q.Key, q.Value);
}
}
return dict;
}
}
Luego, para usar en su vista, simplemente pase el método a la colección de consultas de solicitud actual de Context.Request
:
<a asp-all-route-data="@Model.NextPageLink(Context.Request.Query)">Next</a>
No puede modificar el QueryString directamente ya que es de solo lectura. Necesitará obtener los valores, modificarlos y luego volver a juntarlos. Prueba esto:
var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
nameValues.Set("page", "2");
string url = Request.Url.AbsolutePath;
string updatedQueryString = "?" + nameValues.ToString();
Response.Redirect(url + updatedQueryString);
El método ParseQueryString
devuelve un NameValueCollection
(en realidad, realmente devuelve un HttpValueCollection
que codifica los resultados, como menciono en una respuesta a otra pregunta ). A continuación, puede utilizar el método Set
para actualizar un valor. También puede usar el método Add
para agregar uno nuevo o Remove
para eliminar un valor. Finalmente, al llamar a ToString()
en el nombre NameValueCollection
devuelven los pares de valores de nombre en un formato listo para la consulta de name1=value1&name2=value2
. Una vez que tenga eso, adjúntelo a la URL y redirija.
Alternativamente, puede agregar una nueva clave, o modificar una existente, usando el indexador:
nameValues["temp"] = "hello!"; // add "temp" if it didn''t exist
nameValues["temp"] = "hello, world!"; // overwrite "temp"
nameValues.Remove("temp"); // can''t remove via indexer
Es posible que deba agregar un using System.Collections.Specialized;
Para hacer uso de la clase NameValueCollection
.
Puede hacer esto sin toda la sobrecarga de redirección (lo que no es despreciable). Mi preferencia personal es trabajar con NameValueCollection, que en realidad es una cadena de consulta, pero utilizando la reflexión:
// reflect to readonly property
PropertyInfo isReadOnly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
// make collection editable
isReadOnly.SetValue(this.Request.QueryString, false, null);
// remove
this.Request.QueryString.Remove("foo");
// modify
this.Request.QueryString.Set("bar", "123");
// make collection readonly again
isReadOnly.SetValue(this.Request.QueryString, true, null);
Usando esta clase de ayuda QueryStringBuilder , puede tomar el QueryString actual y llamar al método Add
para cambiar un par de clave / valor existente ...
//before: "?id=123&page=1&sessionId=ABC"
string newQueryString = QueryString.Current.Add("page", "2");
//after: "?id=123&page=2&sessionId=ABC"