2009-04-04 3 views
38

Ho un metodo che restituisce un array (string []) e sto provando a passare questa serie di stringhe in un Azione di collegamento in modo che possa creare una stringa di query simile a:ASP.NET MVC - Passare oggetto array come valore di instradamento all'interno di Html.ActionLink (...)

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

Ma quando mi passa new {str = getStringArray()} ottengo il seguente url:

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

quindi, in pratica si tratta di prendere il mio string [] e in esecuzione .ToString() su di esso per ottenere il valore.

Qualche idea? Grazie!

+7

Avete mai ricevuto una risposta per questo? – reach4thelasers

risposta

-6

Vorrei usare il POST per un array. Oltre ad essere brutto e un abuso di GET, rischi di esaurire lo spazio dell'URL (credici o no).

Assumendo un 2000 byte limit. L'overhead della stringa di query (& str =) riduce a ~ 300 byte di dati effettivi (supponendo che il resto dell'URL sia 0 byte).

12

Provare a creare un RouteValueDictionary contenente i valori. Dovrai assegnare a ciascuna voce una chiave diversa.

<% 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) %> 

vi darà un link come

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

EDIT: MVC2 cambiato l'interfaccia ValueProvider per rendere la mia risposta originale obsoleto. È necessario utilizzare un modello con una serie di stringhe come proprietà.

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

Quindi il raccoglitore modello popolerà il modello con i valori che si passano nell'URL.

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

Ho solo pensato di dire che sembra che tu abbia dato un'altra alternativa a una domanda simile qui a: [ASP.Net MVC RouteData e matrici] (http://stackoverflow.com/questions/1752721/asp-net-mvc-routedata-and-arrays). C'è un modo per collegare queste due domande in modo che le persone possano vedere entrambe le tue alternative? – GuyIncognito

+0

Penso che tu l'abbia appena fatto. In realtà questo non funzionerà più. Aggiornerò il metodo di azione per utilizzare un modello. – tvanfosson

+2

L'associazione modello non è il problema. Sembra che MVC 2 generi ancora stringhe di query come '? Str = System.String% 5B% 5D' quando un valore' RouteValueDictionary' contiene un array/elenco/ecc. Ancora niente da fare? –

2

Questo mi ha veramente infastidito così con inspiration from Scott Hanselman ho scritto il seguente (perfetto) metodo di estensione:

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; 
} 

chiamata in questo modo:

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

C'è una libreria chiamata Unbinder, che puoi usare per inserire oggetti complessi in percorsi/URL.

Funziona così:

using Unbound; 

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

Un'altra soluzione che appena mi è venuta in mente:

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

Questo è sporco e si dovrebbe provarlo prima di usarlo, ma dovrebbe funzionare comunque. Spero che questo ti aiuti.

0

questo è un HelperExtension risolvendo matrice e proprietà IEnumerable guai:

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); 
    } 
} 
Problemi correlati