Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.Net MVC路由数据和阵列_C#_Asp.net Mvc_Arrays_List_Asp.net Mvc Routing - Fatal编程技术网

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看起来还可以,只是编码了(应该是)