2009-04-04 18 views
38

Tengo un método que devuelve una matriz (cadena []) y estoy tratando de pasar esta matriz de cadenas a una Enlace de acción por lo que se creará una cadena de consulta similar a:ASP.NET MVC - Pase objeto de matriz como un valor de ruta dentro de Html.ActionLink (...)

/Controller/Action?str=val1&str=val2&str=val3...etc 

Pero cuando paso nueva {str = GetStringArray()} me sale el siguiente url:

/Controller/Action?str=System.String%5B%5D 

así que básicamente es tomar mi string [] y ejecutando .ToString() en él para obtener el valor.

¿Alguna idea? ¡Gracias!

+7

¿Alguna vez una respuesta para esto? – reach4thelasers

Respuesta

-6

Utilizaría POST para una matriz. Además de ser feo y un abuso de GET, te arriesgas a quedarte sin espacio para URL (lo creas o no).

Suponiendo un 2000 byte limit. La sobrecarga de cadena de consulta (& str =) lo reduce a ~ 300 bytes de datos reales (suponiendo que el resto de la URL es 0 bytes).

12

Intente crear un RouteValueDictionary con sus valores. Tendrás que darle a cada entrada una clave diferente.

<% var rv = new RouteValueDictionary(); 
    var strings = GetStringArray(); 
    for (int i = 0; i < strings.Length; ++i) 
    { 
     rv["str[" + i + "]"] = strings[i]; 
    } 
%> 

<%= Html.ActionLink("Link", "Action", "Controller", rv, null) %> 

le dará un enlace como

<a href='/Controller/Action?str=val0&str=val1&...'>Link</a> 

EDITAR: MVC2 cambió la interfaz ValueProvider para hacer mi primera respuesta obsoleta. Debe usar un modelo con una matriz de cadenas como una propiedad.

public class Model 
{ 
    public string Str[] { get; set; } 
} 

Luego, el modelo de carpeta completará su modelo con los valores que pase en la URL.

public ActionResult Action(Model model) 
{ 
    var str0 = model.Str[0]; 
} 
+1

Sólo pensé que mencionaría que parece que ha dado otra alternativa a una pregunta similar aquí: [ASP.Net MVC RouteData y arrays] (http://stackoverflow.com/questions/1752721/asp-net-mvc-routedata-and-arrays). ¿Hay alguna manera de vincular estas dos preguntas para que las personas puedan ver sus dos alternativas? – GuyIncognito

+0

Creo que acabas de hacerlo. En realidad, esto no funcionará más. Actualizaré el método de acción para usar un modelo. – tvanfosson

+2

El enlace del modelo no es el problema. Parece que MVC 2 aún genera cadenas de consulta como '? Str = System.String% 5B% 5D' cuando un valor' RouteValueDictionary' contiene una matriz/lista/etc. Todavía no hay forma de evitar eso? –

2

Esto realmente me molestó por lo que con inspiration from Scott Hanselman escribí lo siguiente (fluido) método de extensión:

public static RedirectToRouteResult WithRouteValue(
    this RedirectToRouteResult result, 
    string key, 
    object value) 
{ 
    if (value == null) 
     throw new ArgumentException("value cannot be null"); 

    result.RouteValues.Add(key, value); 

    return result; 
} 

public static RedirectToRouteResult WithRouteValue<T>(
    this RedirectToRouteResult result, 
    string key, 
    IEnumerable<T> values) 
{ 
    if (result.RouteValues.Keys.Any(k => k.StartsWith(key + "["))) 
     throw new ArgumentException("Key already exists in collection"); 

    if (values == null) 
     throw new ArgumentNullException("values cannot be null"); 

    var valuesList = values.ToList(); 

    for (int i = 0; i < valuesList.Count; i++) 
    { 
     result.RouteValues.Add(String.Format("{0}[{1}]", key, i), valuesList[i]); 
    } 

    return result; 
} 

llamada así:

return this.RedirectToAction("Index", "Home") 
      .WithRouteValue("id", 1) 
      .WithRouteValue("list", new[] { 1, 2, 3 }); 
1

Hay una biblioteca llamada Unbinder, que puede usar para insertar objetos complejos en rutas/urls.

Funciona así:

using Unbound; 

Unbinder u = new Unbinder(); 
string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(YourComplexObject))); 
2

Otra solución que acaba de llegar a mi mente:

string url = "/Controller/Action?iVal=5&str=" + string.Join("&str=", strArray); 

Esto está sucio y debe probarlo antes de usarlo, pero debería funcionar, sin embargo. Espero que esto ayude.

0

Esta es la solución de un HelperExtension matriz y propiedades IEnumerable problemas:

public static class AjaxHelperExtensions 
{ 
    public static MvcHtmlString ActionLinkWithCollectionModel(this AjaxHelper ajaxHelper, string linkText, string actionName, object model, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) 
    { 
     var rv = new RouteValueDictionary(); 

     foreach (var property in model.GetType().GetProperties()) 
     { 
      if (typeof(ICollection).IsAssignableFrom(property.PropertyType)) 
      { 
       var s = ((IEnumerable<object>)property.GetValue(model)); 
       if (s != null && s.Any()) 
       { 
        var values = s.Select(p => p.ToString()).Where(p => !string.IsNullOrEmpty(p)).ToList(); 
        for (var i = 0; i < values.Count(); i++) 
         rv.Add(string.Concat(property.Name, "[", i, "]"), values[i]); 
       } 
      } 
      else 
      { 
       var value = property.GetGetMethod().Invoke(model, null) == null ? "" : property.GetGetMethod().Invoke(model, null).ToString(); 
       if (!string.IsNullOrEmpty(value)) 
        rv.Add(property.Name, value); 
      } 
     } 
     return System.Web.Mvc.Ajax.AjaxExtensions.ActionLink(ajaxHelper, linkText, actionName, rv, ajaxOptions, htmlAttributes); 
    } 
} 
Cuestiones relacionadas