2009-04-04 4 views
38

У меня есть метод, который возвращает массив (string []), и я пытаюсь передать этот массив строк в Действие Link так, что она будет создавать строку запроса, подобный:ASP.NET MVC - передать объект массива как значение маршрута в Html.ActionLink (...)

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

Но когда я прохожу новый {ул = GetStringArray()} Я получаю следующий URL:

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

поэтому в основном он принимает мой string [] и запустить .ToString() для получения значения.

Любые идеи? Благодаря!

+7

ли вы когда-либо получить ответ на это? – reach4thelasers

ответ

-6

Я бы использовал POST для массива. Помимо уродства и злоупотребления GET, вы рискуете исчерпать пространство URL (верьте или нет).

Предполагая 2000 byte limit. Накладные расходы на строку запроса (& str =) уменьшают до ~ 300 байт фактических данных (при условии, что остальная часть URL-адреса равна 0 байтам).

12

Попробуйте создать документ RouteValueDictionary, содержащий ваши значения. Вы должны будете дать каждой записи другой ключ.

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

даст вам ссылку, как

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

EDIT: MVC2 изменил интерфейс ValueProvider, чтобы сделать мой первоначальный ответ устареет. Вы должны использовать модель с массивом строк как свойство.

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

Затем модельное связующее заполняет вашу модель значениями, которые вы передаете в URL-адресе.

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

Просто подумал, что я бы сказал, что похоже, что вы дали другую альтернативу аналогичному вопросу здесь: [ASP.Net MVC RouteData и массивы] (http://stackoverflow.com/questions/1752721/asp-net-mvc-routedata-and-arrays). Есть ли способ связать эти два вопроса, чтобы люди могли видеть обе ваши альтернативы? – GuyIncognito

+0

Я думаю, что вы только что сделали. На самом деле это больше не будет работать. Я буду обновлять метод действия для использования модели. – tvanfosson

+2

Связывание модели не является проблемой. Кажется, MVC 2 все еще генерирует строки запроса, такие как '? Str = System.String% 5B% 5D', когда значение' RouteValueDictionary' содержит массив/список/etc. Все еще не так? –

2

Это действительно раздражает меня так с inspiration from Scott Hanselman я написал следующее (свободный) метод расширения:

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

вызова, как так:

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

Там есть библиотека называется Unbinder, который вы можете использовать для вставки сложных объектов в маршруты/URL.

Это работает так:

using Unbound; 

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

Другое решение, которое только что пришло мне в голову:

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

Это грязная, и вы должны проверить его, прежде чем использовать его, но он должен работать, тем не менее. Надеюсь это поможет.

0

Это разгадывания HelperExtension массива и IEnumerable свойства неприятности:

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