C# ASP.Net MVC路由数据和阵列
如果我有这样的行为:C# ASP.Net MVC路由数据和阵列,c#,asp.net-mvc,arrays,list,asp.net-mvc-routing,C#,Asp.net Mvc,Arrays,List,Asp.net Mvc Routing,如果我有这样的行为: public ActionResult DoStuff(List<string> stuff) { ... ViewData["stuff"] = stuff; ... return View(); } using Unbound; Unbinder u = new Unbinder(); string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(
public ActionResult DoStuff(List<string> stuff)
{
...
ViewData["stuff"] = stuff;
...
return View();
}
using Unbound;
Unbinder u = new Unbinder();
string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(YourComplexObject)));
但在我的ViewPage中,我有以下代码:
<%= Html.ActionLink("click here", "DoMoreStuff", "MoreStuffController", new { stuff = ViewData["stuff"] }, null) %>
不幸的是,MVC不够聪明,无法识别操作需要一个数组,并展开列表以形成正确的url路由。相反,它只在对象上执行.ToString(),在列表的情况下,该对象只列出数据类型
当目标操作的参数之一是数组或列表时,是否有方法获取Html.ActionLink以生成正确的URL
--编辑--
正如Josh在下面指出的,ViewData[“stuff”]只是一个对象。我试图简化问题,但却导致了一个不相关的错误!我实际上使用了一个专用的ViewPage,所以我有一个紧密耦合的类型感知模型。ActionLink实际上看起来像:
<%= Html.ActionLink("click here", "DoMoreStuff", "MoreStuffController", new { stuff = ViewData.Model.Stuff }, null) %>
其中ViewData.Model.Stuff是以列表形式键入的我认为定制的HtmlHelper应该是合适的
public static string ActionLinkWithList( this HtmlHelper helper, string text, string action, string controller, object routeData, object htmlAttributes )
{
var urlHelper = new UrlHelper( helper.ViewContext.RequestContext );
string href = urlHelper.Action( action, controller );
if (routeData != null)
{
RouteValueDictionary rv = new RouteValueDictionary( routeData );
List<string> urlParameters = new List<string>();
foreach (var key in rv.Keys)
{
object value = rv[key];
if (value is IEnumerable && !(value is string))
{
int i = 0;
foreach (object val in (IEnumerable)value)
{
urlParameters.Add( string.Format( "{0}[{2}]={1}", key, val, i ));
++i;
}
}
else if (value != null)
{
urlParameters.Add( string.Format( "{0}={1}", key, value ) );
}
}
string paramString = string.Join( "&", urlParameters.ToArray() ); // ToArray not needed in 4.0
if (!string.IsNullOrEmpty( paramString ))
{
href += "?" + paramString;
}
}
TagBuilder builder = new TagBuilder( "a" );
builder.Attributes.Add("href",href);
builder.MergeAttributes( new RouteValueDictionary( htmlAttributes ) );
builder.SetInnerText( text );
return builder.ToString( TagRenderMode.Normal );
}
publicstaticstringactionlinkwithlist(此HtmlHelper帮助程序、字符串文本、字符串操作、字符串控制器、对象路由数据、对象htmlAttributes)
{
var urlHelper=新的urlHelper(helper.ViewContext.RequestContext);
string href=urlHelper.Action(Action,controller);
if(routeData!=null)
{
RouteValueDictionary rv=新的RouteValueDictionary(routeData);
List urlParameters=新列表();
foreach(rv.键中的var键)
{
对象值=rv[键];
if(值为IEnumerable&!(值为字符串))
{
int i=0;
foreach(对象值在(IEnumerable)值中)
{
Add(string.Format(“{0}[{2}]={1}”,key,val,i));
++一,;
}
}
else if(值!=null)
{
添加(string.Format(“{0}={1}”,键,值));
}
}
string paramString=string.Join(&),urlParameters.ToArray();//在4.0中不需要ToArray
如果(!string.IsNullOrEmpty(paramString))
{
href+=“?”+参数字符串;
}
}
标记生成器=新标记生成器(“a”);
builder.Attributes.Add(“href”,href);
合并属性(新的RouteValueDictionary(htmlAttributes));
builder.SetInnerText(文本);
返回builder.ToString(TagRenderMode.Normal);
}
我不在我的工作站上,但是像这样的事情怎么样:
<%= Html.ActionLink("click here", "DoMoreStuff", "MoreStuffController", new { stuff = (List<T>)ViewData["stuff"] }, null) %>
或键入:
<%= Html.ActionLink("click here", "DoMoreStuff", "MoreStuffController", new { stuff = (List<T>)ViewData.Model.Stuff }, null) %>
您可以在
路由值后加上如下数组索引:
RouteValueDictionary rv = new RouteValueDictionary();
rv.Add("test[0]", val1);
rv.Add("test[1]", val2);
这将导致查询字符串包含test=val1&test=val2
这可能会有帮助吗?将这两种方法结合起来效果很好
public static RouteValueDictionary FixListRouteDataValues(RouteValueDictionary routes)
{
var newRv = new RouteValueDictionary();
foreach (var key in routes.Keys)
{
object value = routes[key];
if (value is IEnumerable && !(value is string))
{
int index = 0;
foreach (string val in (IEnumerable)value)
{
newRv.Add(string.Format("{0}[{1}]", key, index), val);
index++;
}
}
else
{
newRv.Add(key, value);
}
}
return newRv;
}
然后在任何需要RouteValue和IEnumerable的扩展方法中使用此方法
不幸的是,MVC3中也需要这种变通方法。这只是作为UrlHelper
的扩展,只是提供了一个很好的url,可以放在任何地方,而不是一个完整的a标记,它还将为正在使用的任何其他特定url保留大多数其他路由值。。。为您提供最友好的特定url(减去IEnumerable值),然后在末尾追加查询字符串值
public static string ActionWithList(this UrlHelper helper, string action, object routeData)
{
RouteValueDictionary rv = new RouteValueDictionary(routeData);
var newRv = new RouteValueDictionary();
var arrayRv = new RouteValueDictionary();
foreach (var kvp in rv)
{
var nrv = newRv;
var val = kvp.Value;
if (val is IEnumerable && !(val is string))
{
nrv = arrayRv;
}
nrv.Add(kvp.Key, val);
}
string href = helper.Action(action, newRv);
foreach (var kvp in arrayRv)
{
IEnumerable lst = kvp.Value as IEnumerable;
var key = kvp.Key;
foreach (var val in lst)
{
href = href.AddQueryString(key, val);
}
}
return href;
}
public static string AddQueryString(this string url, string name, object value)
{
url = url ?? "";
char join = '?';
if (url.Contains('?'))
join = '&';
return string.Concat(url, join, name, "=", HttpUtility.UrlEncode(value.ToString()));
}
有一个名为的库,可用于将复杂对象插入路由/URL
它的工作原理如下:
public ActionResult DoStuff(List<string> stuff)
{
...
ViewData["stuff"] = stuff;
...
return View();
}
using Unbound;
Unbinder u = new Unbinder();
string url = Url.RouteUrl("routeName", new RouteValueDictionary(u.Unbind(YourComplexObject)));
ViewData[“stuff”]只是一个对象。当你传入一个真实的列表,比如{Stuff=(list)ViewData[“Stuff”]}或者{Stuff=ViewData[“Stuff”]as list}或者{Stuff=newlist(…)}时会发生什么?同样的问题。。。在我目前的实际实现中,我使用紧密耦合的ViewPage,所以这行看起来更像:其中ViewData.Model.Stuff是以列表的形式键入的。是的,这肯定会起作用。更一般地说,Url生成器(如UrlHelper.Action)和操作参数绑定之间的兼容性应该达到什么级别?我是说,这是虫子还是什么?不,不是虫子。我称之为设计决策。一个参数有多个值的情况非常罕见,尤其是在get上。我认为对象是简单值类型的映射这一期望对大多数人来说都很好。感谢这一点,它让我的想法朝着正确的方向发展。因为字符串是一个将枚举字符的IEnumerable,所以它不会完全起作用。它还生成所有路由参数querystring参数,而原始ActionLink考虑了在global.asax.cs中创建的路由,以格式化支持它的路由参数REST样式。我接受了您的想法,并使用LINQ将所有routedata项作为IEnumerable..提供给我,并用它生成了部分querystring。然后,我获取剩余的路由数据,并向其中添加另一个条目,如“replacemequerystringname”、“replaceMeQueryStringValue”,然后对剩余的路由数据使用常规ActionLink方法。然后,我用前面提到的部分querystringHmmm替换上面已经转换为querystring参数的路由条目。也许可以检查它是否实现了IList而不是IEnumerable?或者专门排除字符串。它仍然会对对象调用ToString()。谢谢,这太棒了。。。哦,等等,没关系,它没用expected@JarrettVUrl看起来还可以,只是编码了(应该是)