2009-04-04 5 views
38

Ich habe eine Methode, die ein Array (string []) zurückgibt und ich versuche, dieses Array von Zeichenfolgen in ein Action-Link, so dass es eine Abfrage-Zeichenfolge ähnlich zu erstellen:ASP.NET MVC - übergeben Array-Objekt als Route-Wert innerhalb Html.ActionLink (...)

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

Aber wenn ich neue passieren {str = GetStringArray()} ich erhalte die folgende uRL:

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

also im Grunde meint es unter string [] und .toString() ausführen, um den Wert zu erhalten.

Irgendwelche Ideen? Vielen Dank!

+7

Haben Sie jemals eine Antwort für diese bekommen? – reach4thelasers

Antwort

-6

Ich würde POST für ein Array verwenden. Abgesehen davon, dass Sie hässlich sind und GET missbrauchen, riskieren Sie, dass Ihnen der URL-Bereich ausgeht (ob Sie es glauben oder nicht).

Angenommen, ein 2000 byte limit. Der Abfragezeichenfolge-Overhead (& str =) reduziert Sie auf ~ 300 Bytes der tatsächlichen Daten (unter der Annahme, dass der Rest der URL 0 Bytes ist).

12

Versuchen Sie, ein RouteValueDictionary mit Ihren Werten zu erstellen. Sie müssen jedem Eintrag einen anderen Schlüssel geben.

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

geben Ihnen einen Link wie

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

EDIT: MVC2 änderte sich die Valueprovider-Schnittstelle meiner ursprünglichen Antwort obsolet zu machen. Sie sollten ein Modell mit einem Array von Strings als Eigenschaft verwenden.

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

Dann wird das Modell Bindemittel wird das Modell mit den Werten füllen, die Sie in der URL übergeben.

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

Nur gedacht, ich würde erwähnen, dass es aussieht, als hätten Sie hier eine andere Alternative zu einer ähnlichen Frage gegeben: [ASP.Net MVC RouteData und Arrays] (http://stackoverflow.com/questions/1752721/asp-net-mvc-routedata-and-arrays). Gibt es eine Möglichkeit, diese beiden Fragen miteinander zu verknüpfen, so dass die Leute beide Alternativen sehen können? – GuyIncognito

+0

Ich denke, du hast es gerade getan. Eigentlich wird das nicht mehr funktionieren. Ich aktualisiere die Aktionsmethode, um ein Modell zu verwenden. – tvanfosson

+2

Die Modellbindung ist nicht das Problem. Es scheint, MVC 2 generiert immer noch Abfragezeichenfolgen wie "? Str = System.String% 5B% 5D", wenn ein 'RouteValueDictionary'-Wert ein Array/list/etc enthält. Immer noch nicht herum? –

2

Das ärgerte mich wirklich so mit inspiration from Scott Hanselman ich folgenden (fließend) Extension-Methode geschrieben:

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

Aufruf wie folgt:

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

Es gibt eine Bibliothek Unbinder, genannt wird, die Sie können komplexe Objekte in Routen/URLs einfügen.

Es funktioniert wie folgt:

using Unbound; 

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

andere Lösung, die mir in den Sinn kam gerade:

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

Das ist schmutzig, und Sie sollten es testen, bevor es zu benutzen, aber es sollte trotzdem funktionieren. Hoffe das hilft.

0

Dies löst eine HelperExtension Array und IEnumerable Eigenschaften Probleme:

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