ASP.NET MVC - 将数组对象作为Html.ActionLink(...)中的路由值传递

时间:2009-04-04 19:46:36

标签: asp.net-mvc arrays actionlink routes

我有一个方法返回一个数组(string []),我试图将这个字符串数组传递给一个Action Link,这样它就会创建一个类似于的查询字符串:

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

但是当我传递新的{str = GetStringArray()}时,我得到以下网址:

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

所以基本上它正在使用我的字符串[]并在其上运行.ToString()来获取值。

有什么想法吗?谢谢!

6 个答案:

答案 0 :(得分:13)

尝试创建一个包含值的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>

编辑:MVC2更改了ValueProvider界面,使我的原始答案过时了。您应该使用带有字符串数组的模型作为属性。

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

然后,模型绑定器将使用您在URL中传递的值填充模型。

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

答案 1 :(得分: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 });

答案 2 :(得分:2)

刚出现在我脑海中的另一个解决方案:

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

这很脏,你应该在使用它之前测试它,但它应该可以工作。希望这会有所帮助。

答案 3 :(得分:1)

有一个名为Unbinder的库,您可以使用它将复杂对象插入路径/网址。

它的工作原理如下:

using Unbound;

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

答案 4 :(得分: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);
    }
}

答案 5 :(得分:-6)

我将POST用于数组。除了丑陋和滥用GET之外,你还有可能用完URL空间(信不信由你)。

假设2000 byte limit。查询字符串开销(&amp; str =)将您减少到大约300字节的实际数据(假设其余的url是0字节)。