Passing IEnumerable property in RouteValues of ActionLink

最后都变了- 提交于 2019-12-11 10:31:58

问题


Imagine an object defined like :

public class MyViewModel{
    public List<string> MyList { get; set; }
}

In my view, i have this Action link :

@Ajax.ActionLink("<", "Index", new MyViewModel() { MyList = new List<string>() {"foo", "bar"}}, new AjaxOptions())

The html result of the ActionLink will be :

<a class="btn btn-default" data-ajax="true" href="/Index?MyList=System.Collections.Generic.List%601%5BSystem.String%5D">&lt;</a>

My question is, how get this result rather :

<a class="btn btn-default" data-ajax="true" href="/Index?MyList=foo&MyList=bar">&lt;</a>

回答1:


You cannot use @Html.ActionLink() to generate route values for a collection. Internally the method (and all the MVC methods that generate urls) uses the .ToString() method of the property to generate the route/query string value (hence your MyList=System.Collections.Generic.List%601%5BSystem.String%5D" result).

The method does not perform recursion on complex properties or collections for good reason - apart from the ugly query string, you could easily exceed the query string limit and throw an exception.

Its not clear why you want to do this (the normal way is to pass an the ID of the object, and then get the data again in the GET method based on the ID), but you can so this by creating a RouteValueDictionary with indexed property names, and use it in your@Ajax.ActionLink() method.

In the view

@{
    var rvd = new RouteValueDictionary();
    rvd.Add("MyList[0]", "foo");
    rvd.Add("MyList[1]", "bar");
}
@Ajax.ActionLink("<", "Index", rvd, new AjaxOptions())

Which will make a GET to

public ActionResult Index(MyViewModel model)

However you must also make MyList a property (the DefaultModelBinder does not bind fields)

public class MyViewModel{
    public List<string> MyList { get; set; } // add getter/setter
}

and then the value of model.MyList in the POST method will be ["foo", "bar"].




回答2:


With Stephen's anwser, i have develop a helper extension method to do this.

Be careful of the URL query string limit : if the collection has too many values, the URL can be greater than 255 characters and throw an exception.

public static class AjaxHelperExtensions
{
    public static MvcHtmlString ActionLinkUsingCollection(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 AjaxExtensions.ActionLink(ajaxHelper, linkText, actionName, rv, ajaxOptions, htmlAttributes);
    }
}



回答3:


You can try string.Join. Something like this

@Ajax.ActionLink(
            "Your text", -- <
            "ActionName", -- Index
            new
            {
               MyList =string.Join(",", new List<string>() {"foo", "bar"}),
              otherPropertiesIfyouwant = YourValue
            }, -- rounteValues
            new AjaxOptions { UpdateTargetId = "..." }, -- Your Ajax option --optional
            new { @id = "back" } -- Your html attribute - optional
            )   


来源:https://stackoverflow.com/questions/46304796/passing-ienumerable-property-in-routevalues-of-actionlink

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!