2011-04-28 19 views
32

Estoy construyendo una URL con el método:Cómo pasar Request.QueryString a Url.Action?

Url.Action("action", "controller"); 

me gustaría transmitir la cadena de consulta de la solicitud actual en esa url también. algo como lo siguiente (pero no funciona): trabajo

public static RouteValueDictionary ToRouteValues(this NameValueCollection queryString) 
    { 
     if (queryString.IsNull() || queryString.HasKeys() == false) return new RouteValueDictionary(); 

     var routeValues = new RouteValueDictionary(); 
     foreach (string key in queryString.AllKeys) 
      routeValues.Add(key, queryString[key]); 

     return routeValues; 
    } 

Con el método de extensión hace el siguiente::

Url.Action("action", "controller", Request.QueryString); 

la conversión de la cadena de consulta a routevalues ​​es posible con la siguiente extensión

Url.Action("action", "controller", Request.QueryString.ToRouteValues()); 

¿Hay alguna otra manera mejor? Thx

+0

Esto generará una excepción si una cadena de consulta contiene dos claves/valores con la misma clave, lo que siempre es una posibilidad ya que alguien puede alterar cadenas de consulta en su navegador –

+3

¡Gracias, esta pregunta es una respuesta realmente útil! ¿Qué es 'querystring.IsNull()' though? ¿Es una extensión personalizada? Porque no lo veo en ningún lado. – hofnarwillie

Respuesta

13

El método de extensión parece correcto y es el camino a seguir.

30

Si quieres ser fácilmente capaz de añadir parámetros adicionales de valor ruta a su Url.Action, probar este método de extensión (basado en el avance de línea de) que toma un objeto anónimo y devuelve un RouteValueCollection:

public static RouteValueDictionary ToRouteValues(this NameValueCollection col, Object obj) 
{ 
    var values = new RouteValueDictionary(obj); 
    if (col != null) 
    { 
     foreach (string key in col) 
     { 
      //values passed in object override those already in collection 
      if (key != null && !values.ContainsKey(key)) values[key] = col[key]; 
     } 
    } 
    return values; 
} 

Entonces puede usarlo de la siguiente manera:

Url.Action("action", "controller", Request.QueryString.ToRouteValues(new{ id=0 })); 
+1

+1 Agregué esto a mi clase de utilidad – shashwat

+1

La primera línea se puede acortar a 'var values ​​= new RouteValueDictionary (obj);'. Como 'RouteValueDictionary (object)' acepta nulos (crea una instancia de un diccionario vacío), el ternario no es necesario. –

0

Aquí está mi solución basada en la respuesta de pwhe23. Quería mantener los parámetros de cadenas de consulta a través de solicitudes POST (debido a un Mvc.Grid) y usar solo una acción para HTTP GET. Las acciones de CRUD se manejan mediante una sola página y diálogos modales dentro (para insertar/actualizar/eliminar).

Así que aquí es mi Extensión:

public static class MvcExtensions 
{ 
    public static RouteValueDictionary ToRouteValues(this NameValueCollection col, Object obj = null) 
    { 
     var values = obj != null ? new RouteValueDictionary(obj) : new RouteValueDictionary(); 

     if (col == null) return values; 

     foreach (string key in col) 
     { 
      //values passed in object are already in collection 
      if (!values.ContainsKey(key)) values[key] = col[key]; 
     } 
     return values; 
    } 
} 

uso en el controlador (por ejemplo, la acción de edición):

[HttpPost] 
    public ActionResult Edit(MyModel model) 
    { 
     // Some stuff 
     return RedirectToAction("Index", Request.QueryString.ToRouteValues()); 
    } 

Formulario para editar generado en Vista (diálogo modal se utiliza):

@using (Html.BeginForm("Edit", "SomeControllerName", Request.QueryString.ToRouteValues(), FormMethod.Post)) 
    { 
     // Some stuff... e.g. dialog content 
    } 
Cuestiones relacionadas