ASP.NET MVC - Pass array object as a route value within Html.ActionLink(…)

前端 未结 6 2115
别跟我提以往
别跟我提以往 2020-12-01 23:13

I have a method that returns an array (string[]) and I\'m trying to pass this array of strings into an Action Link so that it will create a query string similar to:

相关标签:
6条回答
  • 2020-12-01 23:47

    This is a HelperExtension solving array and IEnumerable properties troubles :

    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);
        }
    }
    
    0 讨论(0)
  • 2020-12-01 23:50

    Another solution that just came to my mind:

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

    This is dirty and you should test it before using it, but it should work nevertheless. Hope this helps.

    0 讨论(0)
  • 2020-12-01 23:59

    Try creating a RouteValueDictionary holding your values. You'll have to give each entry a different key.

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

    will give you a link like

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

    EDIT: MVC2 changed the ValueProvider interface to make my original answer obsolete. You should use a model with an array of strings as a property.

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

    Then the model binder will populate your model with the values that you pass in the URL.

    public ActionResult Action( Model model )
    {
        var str0 = model.Str[0];
    }
    
    0 讨论(0)
  • 2020-12-01 23:59

    This really annoyed me so with inspiration from Scott Hanselman I wrote the following (fluent) extension method:

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

    Call like so:

    return this.RedirectToAction("Index", "Home")
               .WithRouteValue("id", 1)
               .WithRouteValue("list", new[] { 1, 2, 3 });
    
    0 讨论(0)
  • 2020-12-01 23:59

    There is a library called Unbinder, which you can use to insert complex objects into routes/urls.

    It works like this:

    using Unbound;
    
    Unbinder u = new Unbinder();
    string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(YourComplexObject)));
    
    0 讨论(0)
  • 2020-12-02 00:06

    I'd use POST for an array. Aside from being ugly and an abuse of GET, you risk running out of URL space (believe it or not).

    Assuming a 2000 byte limit. The query string overhead (&str=) reduces you to ~300 bytes of actual data (assuming the rest of the url is 0 bytes).

    0 讨论(0)
提交回复
热议问题