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:
我有一个方法可以返回一个数组(string[]),我正在尝试将这个字符串数组传递给一个动作链接,这样它就会创建一个类似于:
/Controller/Action?str=val1&str=val2&str=val3...etc
But when I pass new { str = GetStringArray() } I get the following url:
但是当我传递新的{str = GetStringArray()}时,我得到以下url:
/Controller/Action?str=System.String%5B%5D
So basically it's taking my string[] and running .ToString() on it to get the value.
基本上它取我的字符串[]并在上面运行。tostring()来获取值。
Any ideas? Thanks!
什么好主意吗?谢谢!
6 个解决方案
#1
12
Try creating a RouteValueDictionary holding your values. You'll have to give each entry a different key.
尝试创建一个包含您的值的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 ) %>
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.
编辑:MVC2修改了ValueProvider接口,使我的原始答案作废。您应该使用带有字符串数组的模型作为属性。
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.
然后模型绑定器将用您在URL中传递的值填充您的模型。
public ActionResult Action( Model model )
{
var str0 = model.Str[0];
}
#2
2
This really annoyed me so with inspiration from Scott Hanselman I wrote the following (fluent) extension method:
这真的让我很恼火,所以从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;
}
Call like so:
像这样:
return this.RedirectToAction("Index", "Home")
.WithRouteValue("id", 1)
.WithRouteValue("list", new[] { 1, 2, 3 });
#3
2
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.
这是脏的,您应该在使用它之前对它进行测试,但是它仍然可以工作。希望这个有帮助。
#4
1
There is a library called Unbinder, which you can use to insert complex objects into routes/urls.
有一个名为Unbinder的库,您可以使用它将复杂的对象插入到路由/url中。
It works like this:
是这样的:
using Unbound;
Unbinder u = new Unbinder();
string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(YourComplexObject)));
#5
0
This is a HelperExtension solving array and IEnumerable properties troubles :
这是一个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);
}
}
#6
-6
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).
我用POST作为数组。除了丑陋和滥用GET之外,您还可能耗尽URL空间(信不信由您)。
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).
假设有2000字节的限制。查询字符串开销(&str=)将实际数据减少到大约300字节(假设url的其余部分为0字节)。
#1
12
Try creating a RouteValueDictionary holding your values. You'll have to give each entry a different key.
尝试创建一个包含您的值的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 ) %>
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.
编辑:MVC2修改了ValueProvider接口,使我的原始答案作废。您应该使用带有字符串数组的模型作为属性。
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.
然后模型绑定器将用您在URL中传递的值填充您的模型。
public ActionResult Action( Model model )
{
var str0 = model.Str[0];
}
#2
2
This really annoyed me so with inspiration from Scott Hanselman I wrote the following (fluent) extension method:
这真的让我很恼火,所以从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;
}
Call like so:
像这样:
return this.RedirectToAction("Index", "Home")
.WithRouteValue("id", 1)
.WithRouteValue("list", new[] { 1, 2, 3 });
#3
2
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.
这是脏的,您应该在使用它之前对它进行测试,但是它仍然可以工作。希望这个有帮助。
#4
1
There is a library called Unbinder, which you can use to insert complex objects into routes/urls.
有一个名为Unbinder的库,您可以使用它将复杂的对象插入到路由/url中。
It works like this:
是这样的:
using Unbound;
Unbinder u = new Unbinder();
string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(YourComplexObject)));
#5
0
This is a HelperExtension solving array and IEnumerable properties troubles :
这是一个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);
}
}
#6
-6
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).
我用POST作为数组。除了丑陋和滥用GET之外,您还可能耗尽URL空间(信不信由您)。
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).
假设有2000字节的限制。查询字符串开销(&str=)将实际数据减少到大约300字节(假设url的其余部分为0字节)。